{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"# HDA Flowsheet Costing\n",
"\n",
"\n",
"## Note\n",
"\n",
"This tutorial will demonstrate adding capital and operating costs to the two HDA examples, the basic [HDA with Flash](../../Tutorials/Basics/HDA_flowsheet_solution.ipynb) and a comparison with the [HDA with Distillation](HDA_flowsheet_with_distillation_solution.ipynb).\n",
"\n",
"\n",
"## Learning outcomes\n",
"\n",
"\n",
"- Import external pre-built steady-state flowsheets using the IDAES unit model library\n",
"- Define and add costing blocks using the IDAES Process Costing Framework\n",
"- Fomulate and solve a process economics optimization problem\n",
" - 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",
"Users may refer to the prior examples linked at the top of this notebook for detailed process descriptions of the two HDA configurations. As before, the properties required for this module are defined in\n",
"\n",
"- `hda_ideal_VLE.py`\n",
"- `idaes.models.properties.activity_coeff_models.BTX_activity_coeff_VLE`\n",
"- `hda_reaction.py`\n",
"\n",
"Additionally, we will be importing externally-defined flowsheets for the two HDA configurations from\n",
"\n",
"- `hda_flowsheets_for_costing_notebook.py`"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Import and run HDA Flowsheets\n",
"First, we will generate solved flowsheets for each HDA model. The external scripts build and set inputs for the flowsheets, initialize unit models and streams, and solve the flowsheets before returning the model objects. Note that the HDA flowsheets contain all unit models and stream connections, and no costing equations."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The flowsheet utilizes the Wegstein method to iteratively solve circular dependencies such as recycle streams, and is intended to approach a feasible solution. As such, the calls below will fail to converge after 3 iterations and pass to IPOPT to obtain an optimal solution as expected:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Building flowsheet...\n",
"\n",
"Setting inputs...\n",
"\n",
"Initializing flowsheet...\n",
"\n",
"Limiting Wegstein tear to 3 iterations to obtain initial solution, if not converged IPOPT will pick up and continue.\n",
"\n",
"fs.s03\n",
"fs.H101\n",
"fs.R101\n",
"fs.F101\n",
"fs.S101\n",
"fs.C101\n",
"fs.M101\n",
"2022-09-23 09:00:50 [INFO] idaes.init.fs.H101.control_volume: Initialization Complete\n",
"2022-09-23 09:00:50 [INFO] idaes.init.fs.H101: Initialization Complete: optimal - Optimal Solution Found\n",
"2022-09-23 09:00:51 [INFO] idaes.init.fs.R101.control_volume: Initialization Complete\n",
"2022-09-23 09:00:51 [INFO] idaes.init.fs.R101: Initialization Complete: optimal - Optimal Solution Found\n",
"2022-09-23 09:00:51 [INFO] idaes.init.fs.F101.control_volume: Initialization Complete\n",
"2022-09-23 09:00:52 [INFO] idaes.init.fs.F101: Initialization Complete: optimal - Optimal Solution Found\n",
"2022-09-23 09:00:52 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n",
"2022-09-23 09:00:52 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n",
"2022-09-23 09:00:52 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - Optimal Solution Found\n",
"2022-09-23 09:00:52 [INFO] idaes.init.fs.F102.control_volume: Initialization Complete\n",
"2022-09-23 09:00:52 [INFO] idaes.init.fs.F102: Initialization Complete: optimal - Optimal Solution Found\n",
"2022-09-23 09:00:53 [INFO] idaes.init.fs.C101.control_volume: Initialization Complete\n",
"2022-09-23 09:00:53 [INFO] idaes.init.fs.C101: Initialization Complete: optimal - Optimal Solution Found\n",
"2022-09-23 09:00:54 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n",
"2022-09-23 09:00:54 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - Optimal Solution Found\n",
"2022-09-23 09:00:54 [INFO] idaes.init.fs.H101.control_volume: Initialization Complete\n",
"2022-09-23 09:00:55 [INFO] idaes.init.fs.H101: Initialization Complete: optimal - Optimal Solution Found\n",
"2022-09-23 09:00:55 [INFO] idaes.init.fs.R101.control_volume: Initialization Complete\n",
"2022-09-23 09:00:55 [INFO] idaes.init.fs.R101: Initialization Complete: optimal - Optimal Solution Found\n",
"2022-09-23 09:00:56 [INFO] idaes.init.fs.F101.control_volume: Initialization Complete\n",
"2022-09-23 09:00:56 [INFO] idaes.init.fs.F101: Initialization Complete: optimal - Optimal Solution Found\n",
"2022-09-23 09:00:56 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n",
"2022-09-23 09:00:56 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n",
"2022-09-23 09:00:56 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - Optimal Solution Found\n",
"2022-09-23 09:00:57 [INFO] idaes.init.fs.C101.control_volume: Initialization Complete\n",
"2022-09-23 09:00:57 [INFO] idaes.init.fs.C101: Initialization Complete: optimal - Optimal Solution Found\n",
"2022-09-23 09:00:57 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n",
"2022-09-23 09:00:58 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - Optimal Solution Found\n",
"2022-09-23 09:00:58 [INFO] idaes.init.fs.H101.control_volume: Initialization Complete\n",
"2022-09-23 09:00:58 [INFO] idaes.init.fs.H101: Initialization Complete: optimal - Optimal Solution Found\n",
"2022-09-23 09:00:59 [INFO] idaes.init.fs.R101.control_volume: Initialization Complete\n",
"2022-09-23 09:00:59 [INFO] idaes.init.fs.R101: Initialization Complete: optimal - Optimal Solution Found\n",
"2022-09-23 09:00:59 [INFO] idaes.init.fs.F101.control_volume: Initialization Complete\n",
"2022-09-23 09:00:59 [INFO] idaes.init.fs.F101: Initialization Complete: optimal - Optimal Solution Found\n",
"2022-09-23 09:00:59 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n",
"2022-09-23 09:00:59 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n",
"2022-09-23 09:01:00 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - Optimal Solution Found\n",
"2022-09-23 09:01:00 [INFO] idaes.init.fs.C101.control_volume: Initialization Complete\n",
"2022-09-23 09:01:00 [INFO] idaes.init.fs.C101: Initialization Complete: optimal - Optimal Solution Found\n",
"2022-09-23 09:01:01 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n",
"2022-09-23 09:01:01 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - Optimal Solution Found\n",
"2022-09-23 09:01:02 [INFO] idaes.init.fs.H101.control_volume: Initialization Complete\n",
"2022-09-23 09:01:02 [INFO] idaes.init.fs.H101: Initialization Complete: optimal - Optimal Solution Found\n",
"2022-09-23 09:01:02 [INFO] idaes.init.fs.R101.control_volume: Initialization Complete\n",
"2022-09-23 09:01:02 [INFO] idaes.init.fs.R101: Initialization Complete: optimal - Optimal Solution Found\n",
"2022-09-23 09:01:03 [INFO] idaes.init.fs.F101.control_volume: Initialization Complete\n",
"2022-09-23 09:01:03 [INFO] idaes.init.fs.F101: Initialization Complete: optimal - Optimal Solution Found\n",
"2022-09-23 09:01:03 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n",
"2022-09-23 09:01:03 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n",
"2022-09-23 09:01:03 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - Optimal Solution Found\n",
"2022-09-23 09:01:04 [INFO] idaes.init.fs.C101.control_volume: Initialization Complete\n",
"2022-09-23 09:01:04 [INFO] idaes.init.fs.C101: Initialization Complete: optimal - Optimal Solution Found\n",
"2022-09-23 09:01:04 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n",
"2022-09-23 09:01:05 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - Optimal Solution Found\n",
"2022-09-23 09:01:05 [INFO] idaes.init.fs.H101.control_volume: Initialization Complete\n",
"2022-09-23 09:01:05 [INFO] idaes.init.fs.H101: Initialization Complete: optimal - Optimal Solution Found\n",
"2022-09-23 09:01:06 [INFO] idaes.init.fs.R101.control_volume: Initialization Complete\n",
"2022-09-23 09:01:06 [INFO] idaes.init.fs.R101: Initialization Complete: optimal - Optimal Solution Found\n",
"2022-09-23 09:01:06 [INFO] idaes.init.fs.F101.control_volume: Initialization Complete\n",
"2022-09-23 09:01:07 [INFO] idaes.init.fs.F101: Initialization Complete: optimal - Optimal Solution Found\n",
"2022-09-23 09:01:07 [INFO] idaes.init.fs.S101.purge_state: Initialization Complete\n",
"2022-09-23 09:01:07 [INFO] idaes.init.fs.S101.recycle_state: Initialization Complete\n",
"2022-09-23 09:01:07 [INFO] idaes.init.fs.S101: Initialization Step 2 Complete: optimal - Optimal Solution Found\n",
"2022-09-23 09:01:08 [INFO] idaes.init.fs.C101.control_volume: Initialization Complete\n",
"2022-09-23 09:01:08 [INFO] idaes.init.fs.C101: Initialization Complete: optimal - Optimal Solution Found\n",
"2022-09-23 09:01:09 [INFO] idaes.init.fs.M101.mixed_state: Initialization Complete\n",
"2022-09-23 09:01:09 [INFO] idaes.init.fs.M101: Initialization Complete: optimal - Optimal Solution Found\n",
"WARNING: Wegstein failed to converge in 3 iterations\n",
"2022-09-23 09:01:10 [INFO] idaes.init.fs.F102.control_volume: Initialization Complete\n",
"2022-09-23 09:01:10 [INFO] idaes.init.fs.F102: Initialization Complete: optimal - Optimal Solution Found\n",
"Solving flowsheet...\n",
"\n",
"Ipopt 3.13.2: tol=1e-06\n",
"max_iter=5000\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...: 1031\n",
"Number of nonzeros in inequality constraint Jacobian.: 0\n",
"Number of nonzeros in Lagrangian Hessian.............: 907\n",
"\n",
"Total number of variables............................: 340\n",
" variables with only lower bounds: 0\n",
" variables with lower and upper bounds: 146\n",
" variables with only upper bounds: 0\n",
"Total number of equality constraints.................: 340\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.60e+04 0.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n",
" 1 0.0000000e+00 8.69e+03 1.42e+03 -1.0 2.00e+04 - 9.71e-01 4.67e-01H 1\n",
" 2 0.0000000e+00 3.05e+03 1.56e+03 -1.0 1.60e+04 - 9.79e-01 4.90e-01h 1\n",
" 3 0.0000000e+00 1.58e+03 1.55e+05 -1.0 1.41e+04 - 9.90e-01 4.99e-01h 1\n",
" 4 0.0000000e+00 5.49e+02 8.87e+08 -1.0 8.43e+03 - 1.00e+00 9.57e-01h 1\n",
" 5 0.0000000e+00 4.25e+03 2.87e+10 -1.0 8.02e+02 - 1.00e+00 9.90e-01h 1\n",
" 6 0.0000000e+00 2.25e+03 1.51e+10 -1.0 8.39e+00 - 1.00e+00 1.00e+00h 1\n",
" 7 0.0000000e+00 2.27e+01 1.40e+08 -1.0 2.45e-03 - 1.00e+00 1.00e+00f 1\n",
" 8 0.0000000e+00 2.45e-03 1.23e+04 -1.0 2.38e-05 - 1.00e+00 1.00e+00h 1\n",
" 9 0.0000000e+00 7.45e-09 3.87e-01 -2.5 9.06e-08 - 1.00e+00 1.00e+00h 1\n",
"Cannot recompute multipliers for feasibility problem. Error in eq_mult_calculator\n",
"\n",
"Number of Iterations....: 9\n",
"\n",
" (scaled) (unscaled)\n",
"Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n",
"Dual infeasibility......: 2.8284430410926882e+05 2.8284430410926882e+05\n",
"Constraint violation....: 2.9103830456733704e-11 7.4505805969238281e-09\n",
"Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n",
"Overall NLP error.......: 2.9103830456733704e-11 2.8284430410926882e+05\n",
"\n",
"\n",
"Number of objective function evaluations = 11\n",
"Number of objective gradient evaluations = 10\n",
"Number of equality constraint evaluations = 11\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.029\n",
"Total CPU secs in NLP function evaluations = 0.000\n",
"\n",
"EXIT: Optimal Solution Found.\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Complete.\n",
"\n"
]
}
],
"source": [
"# Source file for prebuilt flowsheets\n",
"from hda_flowsheets_for_costing_notebook import hda_with_flash\n",
"# Build hda model with second flash unit and return model object\n",
"m = hda_with_flash(tee=True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## IDAES Process Costing Framework\n",
"IDAES provides a library of capital costing correlations based on those in the following source:\n",
"\n",
"*Process and Product Design Principles: Synthesis, Analysis, and Evaluation*. Seider, Seader, Lewin, Windagdo, 3rd Ed. John Wiley and Sons Chapter 22. Cost Accounting and Capital Cost Estimation 22.2 Cost Indexes and Capital Investment.\n",
"\n",
"Currently, IDAES supports calculation of capital costing for a wide array of unit operations, vesseel sizing and material properties, and specific unit options such as column tray types and heat exchanger configurations. Users may find further information on specific costing methods and options in the IDAES Process Costing Framework documentation (link pending).\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Add Operating Cost Equations\n",
"Before adding capital costing blocks, we will add operating cost equations taken from the basic [HDA with Flash](../../Tutorials/Basics/HDA_flowsheet_solution.ipynb) and the [HDA with Distillation](HDA_flowsheet_with_distillation_solution.ipynb) examples. The examples assume constant cooling and heating coefficients over an annual cost basis. The IDAES Generic Costing Framework does not currently support variable cost calculations."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"# Required imports\n",
"from pyomo.environ import Expression\n",
"\n",
"# Operating costs for HDA with second flash (model m)\n",
"m.fs.cooling_cost = Expression(expr=0.212e-7 * (-m.fs.F101.heat_duty[0]) +\n",
" 0.212e-7 * (-m.fs.R101.heat_duty[0]))\n",
"m.fs.heating_cost = Expression(expr=2.2e-7 * m.fs.H101.heat_duty[0] +\n",
" 1.9e-7 * m.fs.F102.heat_duty[0])\n",
"m.fs.operating_cost = Expression(expr=(3600 * 24 * 365 *\n",
" (m.fs.heating_cost +\n",
" m.fs.cooling_cost)))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Add Capital Costing\n",
"Below, we will add add capital costing blocks to the imported flowsheets and evaluate the economic impact of replacing the second Flash with a Distillation column. First, let's import and define the main flowsheet costing block:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"# Import costing methods - classes, heaters, vessels, compressors, columns\n",
"from idaes.models.costing.SSLW import (\n",
" SSLWCosting,\n",
" SSLWCostingData,\n",
")\n",
"from idaes.core import UnitModelCostingBlock\n",
"\n",
"# Costing block\n",
"m.fs.costing = SSLWCosting()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Next, we will build the relevant costing blocks for the equipment we wish to cost. Note how the costing block, methods and flags are passed as arguments in the costing block call itself. Each unit model will have a single costing block, but each flowsheet model (m and n) will also have a single costing block for flowsheet-level properties.\n",
"\n",
"Users should note that IDAES costing methods support a wide array of heating sources (e.g. fired, steam boiler, hot water) and do not support direct capital costing of coolers. If users wish to cost Heater units acting as coolers, it is necessary to cost a \"dummy\" [0D shell and tube exchanger](https://idaes-pse.readthedocs.io/en/stable/reference_guides/model_libraries/generic/unit_models/heat_exchanger.html) with appropriate aliased hot stream properties and proper cooling water properties. This is not demonstrated here, as the HDA examples take advantage of Flash and Condenser operations to recover liquid product.\n",
"\n",
"Capital costing is independent of unit model connections, and building cost equations may be done piecewise in this fashion. Default options are passed explicitly to demonstrate proper syntax and usage. Now that all required properties are defined, let's cost our models connecting costing blocks, methods and unit models in each flowsheet."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Flexibility of Costing Block Definitions\n",
"IDAES supports many ways to define batches of costing blocks, and several are shown in the example. Users may employ whichever method fits their modeling needs for explicit or concise code. In the code below, note how the unit model itself is never passed to the costing method; when the full model is executed, the costing block will automatically connect its parent block with child equation blocks.\n",
"\n",
"`Compressor` unit models with isothermal or adiabatic thermodynamics are too simple to cost and are therefore excluded from the economic analysis."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's define costing for the heater unit:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"from idaes.models.costing.SSLW import (\n",
" HeaterMaterial,\n",
" HeaterSource,\n",
")\n",
"# Costing for heater - m.fs.H101\n",
"m.fs.H101.costing = UnitModelCostingBlock(\n",
" flowsheet_costing_block=m.fs.costing,\n",
" costing_method=SSLWCostingData.cost_fired_heater,\n",
" costing_method_arguments={\n",
" \"material_type\": HeaterMaterial.CarbonSteel,\n",
" \"heat_source\": HeaterSource.Fuel,\n",
" }\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The costing module provides a `unit_mapping` dictionary linking generic unit model classes with recommended costing methods. In this example, StoichiometricReactor and Flash vessels utilize different vessel costing methods with similar arguments. The diameter and length attributes need to exist in order to cost vessel sizing and material requirements, and we add them if they don't exist already. The `unit_mapping` method provides an opportunity to automatically select the correct vessel orientation (vertical or horizontal) based on the unit type; passing a `StoichiometricReactor` or `PFR` class object will call the `cost_horizontal_vessel` method, while passing a `Flash` or `CSTR` class object will call the `cost_vertical_vessel` method.\n",
"\n",
"All vessels are assigned costing succintly via a loop below - users may define each block individually if desired:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"from idaes.models.costing.SSLW import (\n",
" VesselMaterial,\n",
" TrayType,\n",
" TrayMaterial,\n",
")\n",
"\n",
"from idaes.core.util.constants import Constants\n",
"from pyomo.environ import Var, Constraint, units as pyunits, Param, value\n",
"from idaes.models.unit_models import StoichiometricReactor, Flash\n",
"# Map unit models to unit classes\n",
"# Will pass to unit_mapping which calls costing methods based on unit class\n",
"unit_class_mapping = {m.fs.R101: StoichiometricReactor,\n",
" m.fs.F101: Flash,\n",
" m.fs.F102: Flash,}\n",
"\n",
"# Costing for vessels - m.fs.R101, m.fs.F101, m.fs.F102\n",
"\n",
"# Loop over units\n",
"for unit in [m.fs.R101, m.fs.F101, m.fs.F102]:\n",
" # Get correct unit class for unit model\n",
" unit_class = unit_class_mapping[unit]\n",
" \n",
" # Add dimension variables and constraint if they don't exist\n",
" if not hasattr(unit, \"diameter\"):\n",
" unit.diameter = Var(initialize=1, units=pyunits.m)\n",
" if not hasattr(unit, \"length\"):\n",
" unit.length = Var(initialize=1, units=pyunits.m)\n",
" if hasattr(unit, \"volume\"): # if volume exists, set diameter from volume\n",
" unit.volume_eq = Constraint(expr=unit.volume[0] == unit.length * unit.diameter**2 * 0.25 * Constants.pi)\n",
" else: # fix diameter directly\n",
" unit.diameter.fix(0.2214 * pyunits.m)\n",
" # Either way, fix L/D to calculate L from D\n",
" unit.L_over_D = Constraint(expr=unit.length == 3 * unit.diameter)\n",
" \n",
" # Define vessel costing\n",
" unit.costing = UnitModelCostingBlock(\n",
" flowsheet_costing_block=unit.parent_block().costing, # e.g. m.fs.R101.costing\n",
" costing_method=SSLWCostingData.unit_mapping[unit_class], # e.g. cost_vertical_vessel()\n",
" costing_method_arguments={\n",
" \"material_type\": VesselMaterial.CarbonSteel,\n",
" \"shell_thickness\": 1.25 * pyunits.inch,\n",
"\n",
" }\n",
" )"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Solve Flowsheet Costing Blocks\n",
"Now, we may solve the full flowsheet for all costing blocks:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"# Define solver\n",
"from idaes.core.solvers import get_solver\n",
"solver = get_solver()\n",
"\n",
"# Check that the degrees of freedom are zero\n",
"from idaes.core.util.model_statistics import degrees_of_freedom\n",
"assert degrees_of_freedom(m) == 0"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Ipopt 3.13.2: nlp_scaling_method=gradient-based\n",
"tol=1e-06\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...: 1067\n",
"Number of nonzeros in inequality constraint Jacobian.: 0\n",
"Number of nonzeros in Lagrangian Hessian.............: 915\n",
"\n",
"Total number of variables............................: 358\n",
" variables with only lower bounds: 15\n",
" variables with lower and upper bounds: 146\n",
" variables with only upper bounds: 0\n",
"Total number of equality constraints.................: 358\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.00e+05 1.00e+00 -1.0 0.00e+00 - 0.00e+00 0.00e+00 0\n",
" 1 0.0000000e+00 8.81e+04 5.49e+03 -1.0 9.20e+04 - 2.62e-01 1.20e-01h 1\n",
" 2 0.0000000e+00 6.34e+04 2.46e+03 -1.0 8.10e+04 - 5.83e-01 2.87e-01h 1\n",
" 3 0.0000000e+00 3.40e+04 5.65e+03 -1.0 5.80e+04 - 5.72e-01 4.86e-01h 1\n",
" 4 0.0000000e+00 2.33e+04 5.28e+05 -1.0 3.01e+04 - 7.04e-01 5.09e-01h 1\n",
" 5 0.0000000e+00 1.13e+04 2.99e+09 -1.0 1.49e+04 - 8.02e-01 9.65e-01h 1\n",
" 6 0.0000000e+00 5.50e+03 1.54e+09 -1.0 8.18e+02 - 9.90e-01 6.10e-01h 1\n",
" 7 0.0000000e+00 5.23e+03 1.44e+09 -1.0 3.84e+02 - 9.92e-01 5.07e-02h 1\n",
" 8 0.0000000e+00 5.22e+03 1.44e+09 -1.0 3.70e+02 - 1.00e+00 5.85e-04h 1\n",
" 9r 0.0000000e+00 5.22e+03 1.00e+03 2.3 0.00e+00 - 0.00e+00 3.66e-07R 5\n",
"iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n",
" 10r 0.0000000e+00 6.47e+04 1.34e+04 2.3 1.78e+05 - 2.30e-03 1.09e-03f 1\n",
" 11r 0.0000000e+00 3.63e+04 4.53e+04 2.3 7.67e+03 - 7.32e-02 3.13e-03f 1\n",
" 12r 0.0000000e+00 3.93e+04 4.20e+04 2.3 6.14e+03 - 6.79e-02 1.14e-01f 1\n",
" 13r 0.0000000e+00 3.99e+04 2.20e+04 2.3 6.23e+02 - 4.86e-01 3.05e-01f 1\n",
" 14r 0.0000000e+00 5.25e+04 1.67e+04 2.3 1.89e+03 - 2.37e-01 1.00e+00f 1\n",
" 15r 0.0000000e+00 5.74e+04 8.19e+02 2.3 1.50e+03 - 9.73e-01 7.07e-01f 1\n",
" 16r 0.0000000e+00 5.79e+04 7.74e+02 0.9 5.93e+02 - 9.40e-01 5.52e-01f 1\n",
" 17r 0.0000000e+00 5.77e+04 4.91e+03 0.9 4.87e+02 - 9.04e-01 4.24e-01f 1\n",
" 18r 0.0000000e+00 6.06e+04 1.62e+03 0.9 5.45e+02 - 1.00e+00 6.92e-01f 1\n",
" 19r 0.0000000e+00 6.61e+04 2.32e+02 0.9 2.04e+02 - 1.00e+00 9.52e-01f 1\n",
"iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n",
" 20r 0.0000000e+00 7.62e+04 1.03e+03 0.2 1.71e+02 - 8.32e-01 8.32e-01f 1\n",
" 21r 0.0000000e+00 7.57e+04 8.29e+01 0.2 6.76e+02 - 1.00e+00 1.00e+00f 1\n",
" 22r 0.0000000e+00 7.23e+04 4.74e+01 -0.5 1.37e+02 - 1.00e+00 9.01e-01f 1\n",
" 23r 0.0000000e+00 5.71e+04 3.30e+01 -0.5 7.91e+02 - 1.00e+00 1.00e+00f 1\n",
" 24r 0.0000000e+00 5.85e+04 6.01e-01 -0.5 1.26e+02 - 1.00e+00 1.00e+00h 1\n",
" 25r 0.0000000e+00 4.88e+04 1.78e+02 -2.8 4.53e+02 - 9.80e-01 7.63e-01f 1\n",
" 26r 0.0000000e+00 2.12e+04 2.63e+02 -2.8 2.29e+03 - 4.88e-01 2.16e-01f 1\n",
" 27r 0.0000000e+00 2.05e+04 5.27e+02 -2.8 3.17e+03 - 1.00e+00 3.36e-01f 1\n",
" 28r 0.0000000e+00 2.00e+04 7.36e+02 -2.8 3.93e+03 - 3.18e-02 1.06e-01f 1\n",
" 29r 0.0000000e+00 7.19e+03 7.22e+02 -2.8 4.19e+03 - 1.00e+00 3.22e-01f 1\n",
"iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n",
" 30r 0.0000000e+00 8.95e+03 2.50e+03 -2.8 6.03e+02 - 1.00e+00 7.72e-01f 1\n",
" 31r 0.0000000e+00 5.53e+03 1.10e+03 -2.8 1.82e+03 - 7.92e-01 3.40e-01f 1\n",
" 32r 0.0000000e+00 3.65e+03 7.38e+02 -2.8 1.83e+03 - 6.45e-01 5.76e-01f 1\n",
" 33r 0.0000000e+00 4.19e+02 7.29e+02 -2.8 8.86e+02 - 6.85e-01 8.10e-01f 1\n",
" 34r 0.0000000e+00 2.59e+02 3.88e+02 -2.8 8.93e+01 - 1.00e+00 1.00e+00f 1\n",
" 35r 0.0000000e+00 2.37e+02 3.62e+02 -2.8 8.07e+00 - 1.00e+00 1.00e+00h 1\n",
" 36r 0.0000000e+00 2.37e+02 1.60e+00 -2.8 2.49e+00 - 1.00e+00 1.00e+00h 1\n",
" 37r 0.0000000e+00 2.37e+02 3.54e-02 -2.8 6.73e-02 - 1.00e+00 1.00e+00h 1\n",
" 38r 0.0000000e+00 2.40e+02 6.94e+02 -4.3 1.16e+02 - 1.00e+00 5.13e-01f 1\n",
" 39r 0.0000000e+00 1.40e+02 1.92e+03 -4.3 6.99e+01 - 9.98e-01 4.06e-01f 1\n",
"iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n",
" 40r 0.0000000e+00 8.34e+01 2.11e+03 -4.3 4.21e+01 - 1.00e+00 6.67e-01f 1\n",
" 41r 0.0000000e+00 2.54e+01 6.31e+02 -4.3 2.23e+01 - 7.35e-01 1.00e+00f 1\n",
" 42 0.0000000e+00 2.26e+01 1.16e+07 -1.0 4.76e+01 - 9.90e-01 1.25e-01h 4\n",
" 43 0.0000000e+00 2.00e+01 5.45e+06 -1.0 4.09e+01 - 9.90e-01 1.25e-01h 4\n",
" 44 0.0000000e+00 1.59e+01 4.92e+06 -1.0 3.49e+01 - 9.91e-01 2.50e-01h 3\n",
" 45 0.0000000e+00 1.23e+01 4.33e+06 -1.0 2.41e+01 - 1.00e+00 2.50e-01h 3\n",
" 46 0.0000000e+00 7.56e+00 5.75e+06 -1.0 1.54e+01 - 1.00e+00 5.00e-01h 2\n",
" 47 0.0000000e+00 3.06e+01 1.36e+07 -1.0 1.62e+00 - 1.00e+00 1.00e+00h 1\n",
" 48 0.0000000e+00 3.18e-04 1.31e+03 -1.0 3.34e+01 - 1.00e+00 1.00e+00h 1\n",
" 49 0.0000000e+00 1.49e-08 2.36e-01 -3.8 1.06e-07 - 1.00e+00 1.00e+00h 1\n",
"Cannot recompute multipliers for feasibility problem. Error in eq_mult_calculator\n",
"\n",
"Number of Iterations....: 49\n",
"\n",
" (scaled) (unscaled)\n",
"Objective...............: 0.0000000000000000e+00 0.0000000000000000e+00\n",
"Dual infeasibility......: 1.5041476187401742e+04 1.5041476187401742e+04\n",
"Constraint violation....: 5.8207660913467407e-11 1.4901161193847656e-08\n",
"Complementarity.........: 0.0000000000000000e+00 0.0000000000000000e+00\n",
"Overall NLP error.......: 5.8207660913467407e-11 1.5041476187401742e+04\n",
"\n",
"\n",
"Number of objective function evaluations = 74\n",
"Number of objective gradient evaluations = 19\n",
"Number of equality constraint evaluations = 74\n",
"Number of inequality constraint evaluations = 0\n",
"Number of equality constraint Jacobian evaluations = 51\n",
"Number of inequality constraint Jacobian evaluations = 0\n",
"Number of Lagrangian Hessian evaluations = 49\n",
"Total CPU secs in IPOPT (w/o function evaluations) = 0.118\n",
"Total CPU secs in NLP function evaluations = 0.012\n",
"\n",
"EXIT: Optimal Solution Found.\n"
]
}
],
"source": [
"# Check physical units consistency, solve and check solver status\n",
"from pyomo.environ import TerminationCondition\n",
"from pyomo.util.check_units import assert_units_consistent\n",
"\n",
"assert_units_consistent(m)\n",
"results = solver.solve(m, tee=True, symbolic_solver_labels=True)\n",
"assert results.solver.termination_condition == TerminationCondition.optimal"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"For comparison, we will call and build the HDA flowsheet replacing the second `Flash` with a `TrayColumn` distillation unit model. The flowsheet costing occurs in the external script `hda_flowsheets_for_costing_notebook.py` and is not shown here:"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Building flowsheet...\n",
"\n",
"Setting inputs...\n",
"\n",
"Initializing flowsheet...\n",
"\n",
"Limiting Wegstein tear to 3 iterations to obtain initial solution, if not converged IPOPT will pick up and continue.\n",
"\n",
"WARNING: Wegstein failed to converge in 3 iterations\n",
"Solving flowsheet...\n",
"\n",
"Adding distillation column and resolving flowsheet...\n",
"\n",
"Complete.\n",
"\n"
]
}
],
"source": [
"from pyomo.common.log import LoggingIntercept\n",
"import logging\n",
"from io import StringIO\n",
"\n",
"stream = StringIO()\n",
"with LoggingIntercept(stream, \"idaes\", logging.WARNING):\n",
" # Source file for prebuilt flowsheets\n",
" from hda_flowsheets_for_costing_notebook import hda_with_distillation\n",
" # Build hda model with distillation column and return model object\n",
" n = hda_with_distillation(tee=False)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Results Comparison and Visualization\n",
"For the two flowsheets above, let's sum the total operating and capital costs of each scenario. We will display overall process economics results and compare the two flowsheets:"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"# Imports and data gathering\n",
"from matplotlib import pyplot as plt\n",
"plt.style.use('dark_background') # if using browser in dark mode, uncomment this line\n",
"import numpy as np\n",
"import pandas as pd\n",
"\n",
"# Automatically get units that we costed - this will exclude C101 for both flowsheets\n",
"\n",
"two_flash_unitlist = [getattr(m.fs, unit) for unit in dir(m.fs)\n",
" if hasattr(getattr(m.fs, unit), \"costing\")]\n",
"distillation_unitlist = [getattr(n.fs, unit) for unit in dir(n.fs)\n",
" if hasattr(getattr(n.fs, unit), \"costing\")]"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Costs in $1000:\n"
]
},
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
" \n",
" Equipment | \n",
" fs.H101 | \n",
" fs.R101 | \n",
" fs.F101 | \n",
" fs.F102 | \n",
" fs.D101 | \n",
" fs.H102 | \n",
"
\n",
" \n",
" \n",
" \n",
" Distillation | \n",
" 13.283334 | \n",
" 13.552294 | \n",
" 7.781332 | \n",
" 0.000000 | \n",
" 7.60743 | \n",
" 3.32944 | \n",
"
\n",
" \n",
" Two Flash | \n",
" 13.283334 | \n",
" 10.755878 | \n",
" 7.781332 | \n",
" 7.781332 | \n",
" 0.00000 | \n",
" 0.00000 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
"Equipment fs.H101 fs.R101 fs.F101 fs.F102 fs.D101 fs.H102\n",
"Distillation 13.283334 13.552294 7.781332 0.000000 7.60743 3.32944\n",
"Two Flash 13.283334 10.755878 7.781332 7.781332 0.00000 0.00000"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# Compare equipment purchase costs (actual capital costs)\n",
"\n",
"two_flash_capcost = {unit.name: value(unit.costing.capital_cost/1e3)\n",
" for unit in two_flash_unitlist}\n",
"distillation_capcost = {unit.name: value(unit.costing.capital_cost/1e3)\n",
" for unit in distillation_unitlist}\n",
"\n",
"two_flash_capdf = pd.DataFrame(list(two_flash_capcost.items()),\n",
" columns=['Equipment','Two Flash']).set_index('Equipment')\n",
"distillation_capdf = pd.DataFrame(list(distillation_capcost.items()),\n",
" columns=['Equipment','Distillation']).set_index('Equipment')\n",
"\n",
"# Add dataframes, merge same indices, replace NaNs with 0s, and transpose\n",
"capcosts = two_flash_capdf.add(distillation_capdf, fill_value=0).fillna(0).transpose()\n",
"\n",
"# Sort according to an easier order to view\n",
"capcosts = capcosts[['fs.H101', 'fs.R101', 'fs.F101', 'fs.F102', 'fs.D101', 'fs.H102']]\n",
"\n",
"print('Costs in $1000:')\n",
"display(capcosts) # view dataframe before plotting\n",
"\n",
"capplot = capcosts.plot(kind='bar', stacked=True, title='HDA Total Capital Costs', ylabel='$1000')"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Costs in $1000:\n"
]
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" Utilities | \n",
" cooling | \n",
" heating | \n",
"
\n",
" \n",
" \n",
" \n",
" Distillation | \n",
" 60.193668 | \n",
" 367.399338 | \n",
"
\n",
" \n",
" Two Flash | \n",
" 47.028803 | \n",
" 372.093536 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
"Utilities cooling heating\n",
"Distillation 60.193668 367.399338\n",
"Two Flash 47.028803 372.093536"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# Compare operating costs (per year)\n",
"\n",
"two_flash_opcost = {'cooling': value(3600 * 24 * 365 * m.fs.cooling_cost/1e3),\n",
" 'heating': value(3600 * 24 * 365 * m.fs.heating_cost/1e3)}\n",
"distillation_opcost = {'cooling': value(3600 * 24 * 365 * n.fs.cooling_cost/1e3),\n",
" 'heating': value(3600 * 24 * 365 * n.fs.heating_cost/1e3)}\n",
"\n",
"two_flash_opdf = pd.DataFrame(list(two_flash_opcost.items()),\n",
" columns=['Utilities','Two Flash']).set_index('Utilities')\n",
"distillation_opdf = pd.DataFrame(list(distillation_opcost.items()),\n",
" columns=['Utilities','Distillation']).set_index('Utilities')\n",
"\n",
"# Add dataframes, merge same indices, replace NaNs with 0s, and transpose\n",
"opcosts = two_flash_opdf.add(distillation_opdf, fill_value=0).fillna(0).transpose()\n",
"\n",
"print('Costs in $1000:')\n",
"display(opcosts) # view dataframe before plotting\n",
"\n",
"opplot = opcosts.plot(kind='bar', stacked=True, title='HDA Operating Costs', ylabel='$1000/year')"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Costs in $1000:\n"
]
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" Costs | \n",
" capital | \n",
" operating | \n",
"
\n",
" \n",
" \n",
" \n",
" Distillation | \n",
" 45.553829 | \n",
" 427.593007 | \n",
"
\n",
" \n",
" Two Flash | \n",
" 39.601876 | \n",
" 419.122339 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
"Costs capital operating\n",
"Distillation 45.553829 427.593007\n",
"Two Flash 39.601876 419.122339"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"image/png": "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0NkVKlTAwcGB/Px86tSpww8//ED9+vW5fPlysWXLOnS2RkkVEbnDODk5ERUVhYODA3Z2drz88svXDYRboVAQEbmJlJTkm54lWNK5c+fM1kuisY9ERMSgUBCR8sUOKlSwt3YVfwv29vbFbqW9GYWCiJQrVaqYaNUqSMHwF9nb29OxY0dOnjxZpvV0TUFEypWHHirkuX7d6NrtmTvu3shTp9KtXYLBZDJx8uRJPv300zKtp1AQkXLFwaGQJk0KrV3GLQmyC775QuWcuo9ERMSgUBAREYNCQUREDAoFERExKBRERMSgUBAREYNCQUREDAoFERExKBRERMSgUBAREYNCQUREDAoFERExKBRERMSgUBAREYNCQUREDAoFERExKBRERMSgUBAREYNCQUREDAoFERExKBRERMSgUBAREYNCQUREDAoFERExKBRERMSgUBAREYNCQUREDDcNBTs7O1q0aFHmDVeuXJmdO3eyZ88e9u/fz5gxYwCoXbs2MTExJCYmsmjRIhwcHACoVKkSixYtIjExkZiYGHx9fcu8TxER+WtuGgomk4kvv/yyzBvOz8+nbdu2+Pv74+/vz5NPPklgYCATJ04kPDwcPz8/srKyCAsLAyAsLIysrCz8/PwIDw9n4sSJZT8aERH5S0rVfbRp0yaeeeaZMm/8/PnzADg4OODg4IDJZKJt27YsW7YMgMjISLp27QpAly5diIyMBGDZsmW0a9euzPsTEZG/plSh8MILL7B06VLy8/PJyckhNzeXnJycm2+8QgXi4+NJT09n48aN/PLLL2RnZ1NQUADA6dOn8fLyAsDLy4ukpCQACgoKyMnJwcPD41aPS0REbkHF0izk4uJySxsvLCykSZMmuLq6smLFCh544IFb2s61BgwYwMCBAwHw9PT8y9sTEZH/KVUoALi5ueHn54ejo6Mxbdu2baVaNycnh6ioKFq0aIGbmxv29vYUFBTg7e1NcnIyAMnJyfj4+JCcnIy9vT2urq5kZGQU21ZERAQREREAxMbGlrZ8EREphVJ1H4WFhbF161bWr1/Pe++9x/r16427iW7E09MTV1dXABwdHXn88cc5dOgQUVFRdO/eHYCQkBBWrlwJwKpVqwgJCQGge/fubN68+VaPSUREblGpQuG1114jICCAU6dO0bZtW5o0aUJ2dnaJ69SsWZOoqCj27t1LbGwsGzdu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2BBHR0dj2tixY61YkW3QNQUb1aZNG6KioujWrVuR6ffffz8AK1assEZZIgBMnToVJycn2rRpw4wZM+jevTs///yztcuyCQoFGxUUFERUVBSdO3cuNs9kMikUxKoeeeQRGjduzN69e3n//feZNGkS3333nbXLshkmNdtttWvXLtU0NTVLtpiYGBNg2rFjh6lmzZqmSpUqmRITE61ely003X1k45YvX15s2rJly6xQicj/rFmzBldXVz7++GPi4uI4efIkCxcutHZZNkHdRzaqfv36NGzYEFdX1yLXFVxcXIpc2BOxhg8++ACAb7/9ljVr1uDo6KhbUi1EoWCj6tevT6dOnXBzcytyXSEvL09PM4vV/PnGhz/TtS7z0y2pNq558+bExMRYuwwRAL755psbzjOZTISFhVmwGtukULBxlStXJiwsrNj94PrPJ2KbdKHZxs2dO5caNWrwxBNPEB0djbe3t4YoFquZNWuW8e/g4GArVmLbrH4LlJr1WlxcnAkw7d271wSYKlasaNqxY4fV61KzzfbHzyNg2r17t9XrscWmMwUbd/nyZQCys7ONu5GqVatm5arEVmkkVOvT3Uc2bvr06bi5ufHuu++yatUqqlSpctNXIoqYi7e3N1OmTMHOzs7497Vee+01K1VmO3ShWUTKjZtdR5gzZ46FKrFdCgUbNXTo0BLnh4eHW6gSESlP1H1ko5ydna1dgoiUQzpTEBERg84UbNSfL+D9mS7oidgmhYKN2r17t7VLELkhLy8vPv/8c1q1aoXJZGLbtm289tprJCcnW7s0m2D1hyXU1NTUrm0bNmwwhYaGmuzt7U329vamkJAQ04YNG6xely00XVOwUeHh4QwdOpRVq1Zd94GhLl26WKEqkavi4+Np0qTJTafJ7afuIxs1d+5cAD755BMrVyJSXEZGBn379jVerNO7d28yMjKsXJXtsPrpipr12uDBg0s1TU3Nkq1WrVqmlStXmtLT001paWmmFStWmHx8fKxely00dR/ZuN27d/Pwww8XmRYXF0fTpk2tVJHI1SHd8/PzrV2GTVL3kY3q1asXffr04b777mPlypXGdBcXFzIzM61YmQjs37+ftLQ0tm3bxrZt29i+fbtex2khCgUb9dNPP5GSkoKnpyeTJk0ypufl5ZGQkGDFykTAz88PHx8fHn30UTp27MiXX35Jdna2LjRbgELBRv3666/8+uuvtG/fnosXL2IymfDz8+OBBx5g37591i5PbJyXlxctW7bk0UcfpXHjxhw4cIDt27dbuyybYfULG2rWa7t27TLdddddpnvvvdd04sQJ05IlS0zz5s2zel1qtt0KCgpMMTExpqefftrqtdha00t2bJydnR0XL17kmWee4auvvqJHjx40bNjQ2mWJjbK3twegSZMmzJkzhz59+vDTTz8RGRnJ888/b+XqbIfVk0nNei0uLs7UvHlz044dO0wNGjQwAaaEhASr16Vmm+3aV3DefffdpieeeML0wQcfmE6ePGk6efKk1euzhaZrCjZuyJAhvPXWW6xYsYKDBw9y3333ERUVZe2yxMbFxsZSuXJlfvrpJ7Zu3cpjjz3Gr7/+au2ybIKeUxCRciMpKYnJkydjb29PYWEhQJFhWPTyJ/PTmYKN0thHUh7Z29tTpUoV7OzsrF2KzdKZgo1q2rQpcXFxPPbYY9edv3XrVgtXJHL9J+zFshQKgqenJwBnz561ciVi6zTEivXpllQbNnr0aH777TeOHDnC0aNHSU9P591337V2WWLD2rVrZ+0SbJ5CwUYNHTqUli1bEhAQgIeHB1WrViUwMJCWLVsyZMgQa5cnNiorK8vaJQjl4L5YNcu3uLg4k4eHR7Hpnp6epri4OKvXp6amZp2mMwUb5eDgcN2Xlpw9exYHBwcrVCQi5YFCwUZdunTpluaJyN+b7j6yUVeuXOH8+fPFptvZ2eHo6EilSpWsUJWIWJtCQUREDOo+EhERg0JBREQMCgURETEoFERExKBQEBERw/8DpSiX8QCWu10AAAAASUVORK5CYII=\n",
"text/plain": [
"