From f32ebbb2974ba7d8318c8126f64f4a73a64d1fb0 Mon Sep 17 00:00:00 2001 From: tannerpolley Date: Thu, 12 Jun 2025 16:23:37 -0600 Subject: [PATCH 01/15] 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": "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 }, { - "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": "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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": "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": { + "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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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 3094a8b5664ba65097b566d09aa567356c57a7a7 Mon Sep 17 00:00:00 2001 From: tannerpolley Date: Thu, 26 Jun 2025 11:32:32 -0700 Subject: [PATCH 11/15] 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/15] 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/15] 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/15] 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 25ec437d890bce8cbb1314df81aa39b8d440c141 Mon Sep 17 00:00:00 2001 From: tannerpolley Date: Wed, 3 Dec 2025 12:11:00 -0700 Subject: [PATCH 15/15] 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. --- idaes_examples/mod/hda/hda_ideal_VLE.py | 15 +- .../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 + 11 files changed, 19850 insertions(+), 14212 deletions(-) create mode 100644 idaes_examples/notebooks/docs/tut/core/initializing_testing.py diff --git a/idaes_examples/mod/hda/hda_ideal_VLE.py b/idaes_examples/mod/hda/hda_ideal_VLE.py index b6c3207e..2a7fe1ab 100644 --- a/idaes_examples/mod/hda/hda_ideal_VLE.py +++ b/idaes_examples/mod/hda/hda_ideal_VLE.py @@ -23,6 +23,7 @@ log, NonNegativeReals, Var, + value, Set, Param, sqrt, @@ -45,6 +46,7 @@ LiquidPhase, VaporPhase, ) +from idaes.core.util.model_statistics import degrees_of_freedom from idaes.core.util.constants import Constants as const from idaes.core.util.initialization import fix_state_vars, solve_indexed_blocks from idaes.core.initialization import InitializerBase @@ -548,10 +550,10 @@ def fix_initialization_states(blk): # Fix state variables fix_state_vars(blk) - # Also need to deactivate sum of mole fraction constraint - for k in blk.values(): - if not k.config.defined_state: - k.equilibrium_constraint.deactivate() + # # Also need to deactivate sum of mole fraction constraint + # for k in blk.values(): + # if not k.config.defined_state: + # k.equilibrium_constraint.deactivate() @declare_process_block_class("IdealStateBlock", block_class=_IdealStateBlock) @@ -1011,7 +1013,7 @@ def calculate_dew_point_pressure(self, clear_components=True): # as needed def _temperature_bubble(self): self.temperature_bubble = Param( - initialize=33.0, units=pyunits.K, doc="Bubble point temperature" + initialize=298.15, units=pyunits.K, doc="Bubble point temperature" ) def _temperature_dew(self): @@ -1039,7 +1041,7 @@ def rule_psat_dew(b, j): ) def rule_temp_dew(b): - return ( + ans = ( b.pressure * sum( b.mole_frac_comp[i] / b._p_sat_dewT[i] @@ -1048,6 +1050,7 @@ def rule_temp_dew(b): - 1 == 0 ) + return ans self.eq_temperature_dew = Constraint(rule=rule_temp_dew) except AttributeError: 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()