Byproduct Recovery Framework Tutorial#

The purpose of this tutorial is to introduce the byproduct recovery decision framework (hereafter referenced to as the framework), which is defined in determine_byproduct_recovery.py.The framework assesses the economic viability of converting waste streams into saleable byproducts based on a known viability criterion. This framework serves as a decision-support tool for determining whether specific byproducts should be recovered.

This tutorial gives an example of how to use the framework to determine if lithium and cobalt should be recovered from a diafiltration process. This framework can be generalized to other recoverable byproducts if appropriate pricing data is provided.

To evaluate byproduct recovery, annualized net benefit is assessed with the following equations:

\[ {net\_benefit} = {potential\_revenue} - {total\_recovery\_cost} \newline \newline\]
\[ {potential\_revenue} = \sum_{m} ( {material\_production}_{m} \cdot {market\_value}_{m} + \newline{avoided\_waste\_disposal\_cost}_{m}) \newline \newline\]
\[ {total\_recovery\_cost} = \sum_{m} ( {conversion\_cost}_{m} \cdot {conversion\_possible}_{m} + \newline{added\_process\_cost}_{m} \cdot {added\_process\_steps}_{m}) \newline \newline\]

Definitions of Variables:

  • material_productionₘ: Mass flow rate of recovered byproduct m (kg/yr).

  • market_valueₘ: Market price of byproduct m (USD/kg).

  • avoided_waste_disposal_costₘ: Avoided disposal cost for byproduct m (USD/kg).

  • conversion_costₘ: Annualized cost (considering both CAPEX and OPEX) of the recovery process for byproduct m (USD/yr).

  • conversion_possibleₘ: Binary indicator for whether conversion is required for byproduct m (1 = required, 0 = not required).

  • added_process_costₘ: Annualized cost (considering both CAPEX and OPEX) of additional process units for recovering byproduct m (USD/yr).

  • added_process_stepsₘ: Binary indicator for whether additional process units are required for recovering byproduct m (1 = required, 0 not required).

To use the byproduct recovery framework effectively, a byproduct recovery process with costing must already be constructed. To learn the basics of the REE Costing Framework, please refer to the tutorial on basic costing features in PrOMMiS. This is necessary to determine the annualized cost and annual revenue associated with recovery. Once the process model is built, users can import it—along with its corresponding cost and revenue—and apply the byproduct recovery framework to decide whether or not the byproduct should be recovered.

Learning Objectives: By the end of this tutorial, users will be able to:

  • Decide and import the necessary Python packages

  • Build a process flowsheet using a case study: lithium-cobalt recovery via diafiltration

  • Apply the byproduct recovery decision framework

Step 1: Import the Necessary Packages#

First, import the necessary Pyomo, IDAES, and PrOMMiS packages. These will be implemented at various stages throughout the tutorial.

Package Purposes:

  • Pyomo: Used for model construction and optimization.

  • IDAES: While not essential for this specific tutorial, IDAES models can support model testing and validation.

  • PrOMMiS:

    • prommis.nanofiltration.diafiltration: Used to build the lithium-cobalt diafiltration recovery process model.

    • prommis.uky.costing.costing_dictionaries: Provides product pricing data.

    • prommis.uky.costing.determine_byproduct_recovery: Implements the byproduct recovery decision framework.

For guidance on installing these packages, please refer to the Package Installation section at the end of the tutorial.

# Pyomo packages
from pyomo.environ import (
    ConcreteModel,
    Expression,
    Param,
    TransformationFactory,
    Var,
    value,
)
import pytest

# PrOMMiS packages
from prommis.nanofiltration.diafiltration import (
    main,
    add_costing,
    add_objective,
    add_product_constraints,
    build_model,
    initialize_model,
    set_scaling,
    solve_model,
    unfix_opt_variables,
)
from prommis.uky.costing.costing_dictionaries import load_default_sale_prices
from prommis.uky.costing.determine_byproduct_recovery import (
    ByproductRecovery,
)

Step 2: Building on the Pre-defined Diafiltration Process#

This section gives a brief introduction of how to build upon the pre-defined diafiltration process model. The lithium-cobalt diafiltration process is implemented in the file diafiltration.py, available in the PrOMMiS repository.

To construct a process flowsheet using this existing model, users can refer to the detailed walkthrough provided in the Multi_Stream Contactor Tutorial (Solution). This tutorial outlines the major steps for building the flowsheet.

To determine whether lithium and cobalt should be recovered, the user first needs to build the diafiltration process and access the cost and revenue.

Refer to the process model defined in diafiltration.py. Specifically, call the functions in the order specified within the main() function. Following this order is crucial because the diafiltration process consists of three membrane stages, and the model is built stage by stage.

During each stage of model building, initialization is performed with a set of variables fixed. When transitioning to the next stage, previously fixed variables must be unfixed, and new variables need to be fixed for the current stage. This sequential initialization ensures that the model is stable and properly configured at each membrane stage.

The production rates of lithium and cobalt from the diafiltration process are expressed in kilograms per hour (kg/hr). Assuming the plant operates 8,000 hours annually, the annual production of lithium and cobalt can be calculated by multiplying the hourly production rates by 8,000 hr/yr.

Note that the code may generate warnings related to volumetric flow being temporarily set to zero during initialization—values that fall outside the predefined variable bounds. These warnings do not affect model performance and can be safely ignored.

# Build and solve the model
m = build_model()
add_costing(m)
initialize_model(m)
solve_model(m)

unfix_opt_variables(m)
add_product_constraints(m, Li_recovery_bound=0.95, Co_recovery_bound=0.635)
add_objective(m)
set_scaling(m)

solve_model(m)

# Store results for later application in the framework
total_annualized_cost = value(m.fs.costing.total_annualized_cost)

# recovery mass flow rate annually: kg/hr * 8000 hr/yr
Li_recovery_mass = value(m.fs.stage3.permeate_outlet.flow_vol[0]) * value(
    m.fs.stage3.permeate_outlet.conc_mass_solute[0, "Li"] * 8000
)
Co_recovery_mass = value(m.fs.stage1.retentate_outlet.flow_vol[0]) * value(
    m.fs.stage1.retentate_outlet.conc_mass_solute[0, "Co"] * 8000
)
WARNING (W1002): Setting Var 'fs.stage1.permeate[0.0,1].flow_vol' to a numeric
value `0.0` outside the bounds (1e-08, None).
    See also https://pyomo.readthedocs.io/en/stable/errors.html#w1002
WARNING (W1002): Setting Var 'fs.stage1.permeate[0.0,2].flow_vol' to a numeric
value `0.0` outside the bounds (1e-08, None).
    See also https://pyomo.readthedocs.io/en/stable/errors.html#w1002
WARNING (W1002): Setting Var 'fs.stage1.permeate[0.0,3].flow_vol' to a numeric
value `0.0` outside the bounds (1e-08, None).
    See also https://pyomo.readthedocs.io/en/stable/errors.html#w1002
WARNING (W1002): Setting Var 'fs.stage1.permeate[0.0,4].flow_vol' to a numeric
value `0.0` outside the bounds (1e-08, None).
    See also https://pyomo.readthedocs.io/en/stable/errors.html#w1002
WARNING (W1002): Setting Var 'fs.stage1.permeate[0.0,5].flow_vol' to a numeric
value `0.0` outside the bounds (1e-08, None).
    See also https://pyomo.readthedocs.io/en/stable/errors.html#w1002
WARNING (W1002): Setting Var 'fs.stage1.permeate[0.0,6].flow_vol' to a numeric
value `0.0` outside the bounds (1e-08, None).
    See also https://pyomo.readthedocs.io/en/stable/errors.html#w1002
WARNING (W1002): Setting Var 'fs.stage1.permeate[0.0,7].flow_vol' to a numeric
value `0.0` outside the bounds (1e-08, None).
    See also https://pyomo.readthedocs.io/en/stable/errors.html#w1002
WARNING (W1002): Setting Var 'fs.stage1.permeate[0.0,8].flow_vol' to a numeric
value `0.0` outside the bounds (1e-08, None).
    See also https://pyomo.readthedocs.io/en/stable/errors.html#w1002
WARNING (W1002): Setting Var 'fs.stage1.permeate[0.0,9].flow_vol' to a numeric
value `0.0` outside the bounds (1e-08, None).
    See also https://pyomo.readthedocs.io/en/stable/errors.html#w1002
WARNING (W1002): Setting Var 'fs.stage1.permeate[0.0,10].flow_vol' to a
numeric value `0.0` outside the bounds (1e-08, None).
    See also https://pyomo.readthedocs.io/en/stable/errors.html#w1002
2025-12-08 13:25:09 [INFO] idaes.init.fs.stage1: Stream Initialization Completed.
2025-12-08 13:25:09 [INFO] idaes.init.fs.stage1: Initialization Completed, optimal - <undefined>
2025-12-08 13:25:10 [INFO] idaes.init.fs.mix1: Initialization Complete: optimal - <undefined>
WARNING (W1002): Setting Var 'fs.stage2.permeate[0.0,1].flow_vol' to a numeric
value `0.0` outside the bounds (1e-08, None).
    See also https://pyomo.readthedocs.io/en/stable/errors.html#w1002
WARNING (W1002): Setting Var 'fs.stage2.permeate[0.0,2].flow_vol' to a numeric
value `0.0` outside the bounds (1e-08, None).
    See also https://pyomo.readthedocs.io/en/stable/errors.html#w1002
WARNING (W1002): Setting Var 'fs.stage2.permeate[0.0,3].flow_vol' to a numeric
value `0.0` outside the bounds (1e-08, None).
    See also https://pyomo.readthedocs.io/en/stable/errors.html#w1002
WARNING (W1002): Setting Var 'fs.stage2.permeate[0.0,4].flow_vol' to a numeric
value `0.0` outside the bounds (1e-08, None).
    See also https://pyomo.readthedocs.io/en/stable/errors.html#w1002
WARNING (W1002): Setting Var 'fs.stage2.permeate[0.0,5].flow_vol' to a numeric
value `0.0` outside the bounds (1e-08, None).
    See also https://pyomo.readthedocs.io/en/stable/errors.html#w1002
WARNING (W1002): Setting Var 'fs.stage2.permeate[0.0,6].flow_vol' to a numeric
value `0.0` outside the bounds (1e-08, None).
    See also https://pyomo.readthedocs.io/en/stable/errors.html#w1002
WARNING (W1002): Setting Var 'fs.stage2.permeate[0.0,7].flow_vol' to a numeric
value `0.0` outside the bounds (1e-08, None).
    See also https://pyomo.readthedocs.io/en/stable/errors.html#w1002
WARNING (W1002): Setting Var 'fs.stage2.permeate[0.0,8].flow_vol' to a numeric
value `0.0` outside the bounds (1e-08, None).
    See also https://pyomo.readthedocs.io/en/stable/errors.html#w1002
WARNING (W1002): Setting Var 'fs.stage2.permeate[0.0,9].flow_vol' to a numeric
value `0.0` outside the bounds (1e-08, None).
    See also https://pyomo.readthedocs.io/en/stable/errors.html#w1002
WARNING (W1002): Setting Var 'fs.stage2.permeate[0.0,10].flow_vol' to a
numeric value `0.0` outside the bounds (1e-08, None).
    See also https://pyomo.readthedocs.io/en/stable/errors.html#w1002
2025-12-08 13:25:10 [INFO] idaes.init.fs.stage2: Stream Initialization Completed.
2025-12-08 13:25:10 [INFO] idaes.init.fs.stage2: Initialization Completed, optimal - <undefined>
2025-12-08 13:25:10 [INFO] idaes.init.fs.mix2: Initialization Complete: optimal - <undefined>
WARNING (W1002): Setting Var 'fs.stage3.permeate[0.0,1].flow_vol' to a numeric
value `0.0` outside the bounds (1e-08, None).
    See also https://pyomo.readthedocs.io/en/stable/errors.html#w1002
WARNING (W1002): Setting Var 'fs.stage3.permeate[0.0,2].flow_vol' to a numeric
value `0.0` outside the bounds (1e-08, None).
    See also https://pyomo.readthedocs.io/en/stable/errors.html#w1002
WARNING (W1002): Setting Var 'fs.stage3.permeate[0.0,3].flow_vol' to a numeric
value `0.0` outside the bounds (1e-08, None).
    See also https://pyomo.readthedocs.io/en/stable/errors.html#w1002
WARNING (W1002): Setting Var 'fs.stage3.permeate[0.0,4].flow_vol' to a numeric
value `0.0` outside the bounds (1e-08, None).
    See also https://pyomo.readthedocs.io/en/stable/errors.html#w1002
WARNING (W1002): Setting Var 'fs.stage3.permeate[0.0,5].flow_vol' to a numeric
value `0.0` outside the bounds (1e-08, None).
    See also https://pyomo.readthedocs.io/en/stable/errors.html#w1002
WARNING (W1002): Setting Var 'fs.stage3.permeate[0.0,6].flow_vol' to a numeric
value `0.0` outside the bounds (1e-08, None).
    See also https://pyomo.readthedocs.io/en/stable/errors.html#w1002
WARNING (W1002): Setting Var 'fs.stage3.permeate[0.0,7].flow_vol' to a numeric
value `0.0` outside the bounds (1e-08, None).
    See also https://pyomo.readthedocs.io/en/stable/errors.html#w1002
WARNING (W1002): Setting Var 'fs.stage3.permeate[0.0,8].flow_vol' to a numeric
value `0.0` outside the bounds (1e-08, None).
    See also https://pyomo.readthedocs.io/en/stable/errors.html#w1002
WARNING (W1002): Setting Var 'fs.stage3.permeate[0.0,9].flow_vol' to a numeric
value `0.0` outside the bounds (1e-08, None).
    See also https://pyomo.readthedocs.io/en/stable/errors.html#w1002
WARNING (W1002): Setting Var 'fs.stage3.permeate[0.0,10].flow_vol' to a
numeric value `0.0` outside the bounds (1e-08, None).
    See also https://pyomo.readthedocs.io/en/stable/errors.html#w1002
2025-12-08 13:25:10 [INFO] idaes.init.fs.stage3: Stream Initialization Completed.
2025-12-08 13:25:10 [INFO] idaes.init.fs.stage3: Initialization Completed, optimal - <undefined>
2025-12-08 13:25:10 [INFO] idaes.init.fs.stage3: Stream Initialization Completed.
2025-12-08 13:25:10 [INFO] idaes.init.fs.stage3: Initialization Completed, optimal - <undefined>
Ipopt 3.13.2: max_iter=3000


******************************************************************************
This program contains Ipopt, a library for large-scale nonlinear optimization.
 Ipopt is released as open source code under the Eclipse Public License (EPL).
         For more information visit http://projects.coin-or.org/Ipopt

This version of Ipopt was compiled from source code available at
    https://github.com/IDAES/Ipopt as part of the Institute for the Design of
    Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE
    Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.

This version of Ipopt was compiled using HSL, a collection of Fortran codes
    for large-scale scientific computation.  All technical papers, sales and
    publicity material resulting from use of the HSL codes within IPOPT must
    contain the following acknowledgement:
        HSL, a collection of Fortran codes for large-scale scientific
        computation. See http://www.hsl.rl.ac.uk.
******************************************************************************

This is Ipopt version 3.13.2, running with linear solver ma27.

Number of nonzeros in equality constraint Jacobian...:     1154
Number of nonzeros in inequality constraint Jacobian.:        0
Number of nonzeros in Lagrangian Hessian.............:      239

Total number of variables............................:      320
                     variables with only lower bounds:      225
                variables with lower and upper bounds:        0
                     variables with only upper bounds:        0
Total number of equality constraints.................:      320
Total number of inequality constraints...............:        0
        inequality constraints with only lower bounds:        0
   inequality constraints with lower and upper bounds:        0
        inequality constraints with only upper bounds:        0

iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
   0  0.0000000e+00 3.00e+05 1.00e+00  -1.0 0.00e+00    -  0.00e+00 0.00e+00   0
   1  0.0000000e+00 4.72e+03 3.23e+07  -1.0 1.43e+05    -  9.43e-05 9.90e-01f  1
   2  0.0000000e+00 4.77e+01 3.12e+03  -1.0 5.76e+03    -  9.38e-01 9.90e-01h  1
   3  0.0000000e+00 4.61e-01 1.82e+00  -1.0 5.81e+01    -  9.90e-01 9.90e-01h  1
   4  0.0000000e+00 4.39e-09 5.09e+01  -1.0 5.61e-01    -  9.91e-01 1.00e+00h  1

Number of Iterations....: 4

                                   (scaled)                 (unscaled)
Objective...............:   0.0000000000000000e+00    0.0000000000000000e+00
Dual infeasibility......:   0.0000000000000000e+00    0.0000000000000000e+00
Constraint violation....:   4.2942195345314488e-10    4.3946783989667892e-09
Complementarity.........:   0.0000000000000000e+00    0.0000000000000000e+00
Overall NLP error.......:   4.2942195345314488e-10    4.3946783989667892e-09


Number of objective function evaluations             = 5
Number of objective gradient evaluations             = 5
Number of equality constraint evaluations            = 5
Number of inequality constraint evaluations          = 0
Number of equality constraint Jacobian evaluations   = 5
Number of inequality constraint Jacobian evaluations = 0
Number of Lagrangian Hessian evaluations             = 4
Total CPU secs in IPOPT (w/o function evaluations)   =      0.000
Total CPU secs in NLP function evaluations           =      0.000

EXIT: Optimal Solution Found.
Ipopt 3.13.2: max_iter=3000


******************************************************************************
This program contains Ipopt, a library for large-scale nonlinear optimization.
 Ipopt is released as open source code under the Eclipse Public License (EPL).
         For more information visit http://projects.coin-or.org/Ipopt

This version of Ipopt was compiled from source code available at
    https://github.com/IDAES/Ipopt as part of the Institute for the Design of
    Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE
    Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.

This version of Ipopt was compiled using HSL, a collection of Fortran codes
    for large-scale scientific computation.  All technical papers, sales and
    publicity material resulting from use of the HSL codes within IPOPT must
    contain the following acknowledgement:
        HSL, a collection of Fortran codes for large-scale scientific
        computation. See http://www.hsl.rl.ac.uk.
******************************************************************************

This is Ipopt version 3.13.2, running with linear solver ma27.

Number of nonzeros in equality constraint Jacobian...:     1187
Number of nonzeros in inequality constraint Jacobian.:        4
Number of nonzeros in Lagrangian Hessian.............:      240

Total number of variables............................:      323
                     variables with only lower bounds:      225
                variables with lower and upper bounds:        0
                     variables with only upper bounds:        0
Total number of equality constraints.................:      320
Total number of inequality constraints...............:        2
        inequality constraints with only lower bounds:        2
   inequality constraints with lower and upper bounds:        0
        inequality constraints with only upper bounds:        0

iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
   0  1.4888929e+05 3.41e+01 1.00e+00  -1.0 0.00e+00    -  0.00e+00 0.00e+00   0
   1  1.4887439e+05 3.37e+01 7.70e+01  -1.0 5.16e+03    -  7.35e-01 1.03e-02f  1
   2  1.4887444e+05 3.37e+01 1.38e+05  -1.0 3.70e+03    -  1.89e-01 1.06e-04h  1
   3  1.4921075e+05 1.11e+05 1.38e+05  -1.0 4.26e+05    -  3.45e-03 3.45e-03s 14
   4  1.4642633e+05 1.11e+05 7.46e+05  -1.0 7.31e+06    -  2.90e-03 0.00e+00S 14
   5  1.4642734e+05 1.11e+05 8.00e+05  -1.0 3.08e+06    -  1.89e-03 5.26e-05h  1
   6  1.4647440e+05 1.11e+05 8.47e+05  -1.0 3.21e+06    -  1.87e-03 7.45e-05h  5
   7  1.4654239e+05 1.11e+05 9.07e+05  -1.0 3.22e+06    -  2.52e-03 1.07e-04h  6
   8  1.4660752e+05 1.11e+05 9.85e+05  -1.0 3.24e+06    -  3.44e-03 1.02e-04h  7
   9  1.4666297e+05 1.11e+05 1.09e+06  -1.0 3.26e+06    -  4.98e-03 8.62e-05h  8
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
  10  1.4670926e+05 1.11e+05 1.24e+06  -1.0 3.27e+06    -  8.18e-03 7.16e-05h  9
  11  1.4679193e+05 1.11e+05 1.28e+06  -1.0 3.28e+06    -  3.18e-03 1.27e-04h  9
  12  1.4683964e+05 1.11e+05 1.44e+06  -1.0 3.31e+06    -  1.28e-02 7.29e-05h 10
  13  1.4688175e+05 1.11e+05 1.47e+06  -1.0 3.32e+06    -  2.99e-03 6.40e-05h 11
  14  1.4692761e+05 1.11e+05 1.69e+06  -1.0 3.33e+06    -  2.99e-02 6.95e-05h 11
  15  1.4489278e+05 1.11e+05 1.68e+06  -1.0 3.34e+06    -  1.64e-03 5.97e-04H  1
  16  1.4506504e+05 1.11e+05 1.68e+06  -1.0 2.78e+06    -  3.14e-05 3.21e-04h  4
  17  1.4530663e+05 1.11e+05 1.69e+06  -1.0 2.82e+06    -  1.40e-03 4.43e-04h  9
  18  1.4551152e+05 1.11e+05 1.69e+06  -1.0 2.88e+06    -  1.15e-03 3.67e-04h  7
  19  1.4576268e+05 1.11e+05 1.69e+06  -1.0 2.93e+06    -  6.58e-03 4.41e-04h  8
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
  20  1.4599634e+05 1.11e+05 1.69e+06  -1.0 2.99e+06    -  1.83e-03 4.01e-04h  9
  21  1.4632019e+05 1.11e+05 1.72e+06  -1.0 3.05e+06    -  3.46e-02 5.43e-04h  9
  22  1.4479963e+05 1.11e+05 1.71e+06  -1.0 3.13e+06    -  2.05e-03 4.78e-04H  1
  23  1.4484987e+05 1.11e+05 1.71e+06  -1.0 2.76e+06    -  5.56e-05 9.48e-05h  8
  24  1.4488931e+05 1.11e+05 1.71e+06  -1.0 2.77e+06    -  4.91e-04 7.40e-05h  9
  25  1.4489582e+05 1.11e+05 1.71e+06  -1.0 2.78e+06    -  2.84e-04 1.22e-05h 12
  26  1.4613849e+05 1.11e+05 1.70e+06  -1.0 2.78e+06    -  2.32e-03 2.32e-03s 17
  27  1.4823329e+05 1.10e+05 1.70e+06  -1.0 3.04e+06    -  3.53e-03 3.53e-03s 17
  28  1.6057594e+05 1.08e+05 1.67e+06  -1.0 3.46e+06    -  1.80e-02 1.80e-02s 17
  29  1.7357458e+05 1.06e+05 1.63e+06  -1.0 3.29e+06    -  2.05e-02 2.05e-02s 17
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
  30  1.7369354e+05 1.06e+05 1.63e+06  -1.0 3.24e+06    -  1.94e-04 1.94e-04s 17
  31r 1.7369354e+05 1.06e+05 1.00e+03   2.5 0.00e+00    -  0.00e+00 0.00e+00R  1
  32r 1.7353106e+05 1.06e+05 2.91e+04   2.5 4.12e+05    -  6.33e-03 4.34e-03f  1
  33r 1.7352190e+05 1.06e+05 2.90e+04   2.5 5.62e+03    -  1.05e-01 2.73e-03f  1
  34r 1.7321001e+05 8.24e+04 2.58e+04   2.5 3.12e+03    -  1.37e-03 1.13e-01f  1
  35r 1.7317652e+05 6.19e+03 2.48e+04   2.5 9.27e+03    -  2.35e-01 4.14e-02f  1
  36r 1.7313413e+05 7.39e+03 2.42e+04   2.5 1.94e+03    -  3.79e-01 2.34e-02f  1
  37r 1.7317813e+05 1.00e+04 3.74e+04   2.5 4.08e+02    -  1.00e+00 1.09e-01f  1
  38r 1.7384384e+05 5.71e+03 2.10e+04   2.5 1.59e+03    -  2.85e-01 4.29e-01f  1
  39r 1.7334485e+05 6.62e+01 3.53e+03   2.5 5.28e+02    -  1.00e+00 1.00e+00f  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
  40r 1.7356518e+05 8.35e+00 1.75e+03   1.8 4.90e+02    -  1.00e+00 5.56e-01f  1
  41r 1.7416704e+05 1.75e+01 2.62e+03   1.1 9.68e+02    -  1.00e+00 6.67e-01f  1
  42r 1.7530786e+05 5.32e+00 5.71e+03   1.1 1.75e+03    -  1.00e+00 6.81e-01f  1
  43r 1.7583931e+05 3.57e+00 4.60e+01   1.1 5.54e+02    -  1.00e+00 1.00e+00f  1
  44r 1.7585805e+05 1.32e+00 2.36e+03  -0.3 4.29e+01    -  1.00e+00 6.90e-01f  1
  45r 1.8185926e+05 6.12e+02 2.57e+03  -0.3 1.15e+04    -  7.75e-01 5.54e-01f  1
  46r 1.8190967e+05 6.04e+02 4.36e+03  -0.3 4.29e+03    -  1.00e+00 1.26e-02f  1
  47r 1.8160397e+05 2.33e+01 5.21e+01  -0.3 3.31e+02    -  1.00e+00 1.00e+00f  1
  48  1.8159886e+05 2.33e+01 1.14e+03  -1.0 3.79e+04    -  6.08e-01 5.83e-04f  1
  49  1.8162061e+05 8.95e+01 1.14e+03  -1.0 1.23e+05    -  7.41e-04 7.41e-04s 12
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
  50  1.8242765e+05 1.06e+05 1.11e+03  -1.0 1.23e+05    -  3.01e-02 3.01e-02s 12
  51  1.7462529e+05 1.06e+05 1.10e+03  -1.0 1.46e+06    -  5.88e-03 5.88e-03s 12
  52r 1.7462529e+05 1.06e+05 1.00e+03   2.1 0.00e+00    -  0.00e+00 0.00e+00R  1
  53r 1.7454386e+05 5.23e+04 5.80e+03   2.1 4.75e+03    -  8.11e-05 1.84e-02f  1
  54r 1.7453172e+05 9.65e+01 6.79e+04   2.1 1.11e+04    -  4.12e-01 6.14e-03f  1
  55r 1.7455216e+05 5.71e+02 7.93e+03   2.1 2.38e+02    -  9.92e-01 8.17e-02f  1
  56r 1.7488245e+05 8.70e+01 1.17e+04   2.1 3.80e+02    -  6.54e-01 8.47e-01f  1
  57r 1.7492871e+05 1.18e+01 1.22e+00   2.1 5.57e+01    -  1.00e+00 1.00e+00f  1
  58r 1.7494729e+05 4.60e+00 2.86e+03   0.0 8.34e+01    -  9.95e-01 7.06e-01f  1
  59r 1.7689159e+05 9.38e+00 1.09e+04   0.0 3.82e+03    -  9.06e-01 5.31e-01f  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
  60r 1.7800875e+05 4.16e+00 6.18e+03   0.0 1.78e+03    -  1.00e+00 6.47e-01f  1
  61r 1.7861669e+05 8.15e-01 4.62e+01   0.0 6.39e+02    -  1.00e+00 1.00e+00f  1
  62  1.7850768e+05 1.01e+02 1.55e+02  -1.0 8.74e+04    -  5.27e-02 1.98e-03f  6
  63  1.7840496e+05 2.01e+02 1.54e+02  -1.0 1.76e+05    -  1.65e-03 1.17e-03f  6
  64  1.7835224e+05 2.26e+02 1.58e+02  -1.0 2.14e+05    -  3.31e-02 5.12e-04f  7
  65  1.7829760e+05 2.51e+02 1.58e+02  -1.0 1.92e+05    -  4.48e-03 5.67e-04f  7
  66  1.7824184e+05 2.76e+02 1.63e+02  -1.0 1.91e+05    -  4.24e-02 5.79e-04f  7
  67  1.7444361e+05 1.02e+05 3.08e+02  -1.0 1.44e+05    -  8.61e-03 4.72e-02f  1
  68  1.7087847e+05 1.01e+05 2.32e+02  -1.0 2.65e+05    -  7.36e-01 1.36e-02f  1
  69  1.6787255e+05 9.88e+04 2.59e+03  -1.0 1.55e+05    -  9.90e-01 2.28e-02f  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
  70  1.6784879e+05 9.88e+04 4.70e+05  -1.0 9.89e+04    -  8.76e-01 2.62e-04f  1
  71  1.5444610e+05 8.87e+04 4.22e+05  -1.0 1.47e+06    -  6.12e-02 1.02e-01H  1
  72  1.6328721e+05 8.12e+04 3.46e+05  -1.0 8.45e+05    -  1.61e-03 8.44e-02h  3
  73  1.6573611e+05 7.99e+04 3.90e+05  -1.0 1.04e+06    -  1.46e-01 1.58e-02h  5
  74  1.6697581e+05 7.93e+04 4.37e+05  -1.0 1.09e+06    -  1.63e-01 7.51e-03h  6
  75  1.6758524e+05 7.91e+04 4.90e+05  -1.0 1.11e+06    -  2.00e-01 3.58e-03h  7
  76  1.6773701e+05 7.90e+04 5.26e+05  -1.0 1.11e+06    -  1.63e-01 8.78e-04h  9
  77  1.7166961e+05 7.73e+04 5.13e+05  -1.0 1.04e+06    -  8.50e-03 2.09e-02h  1
  78  2.1078104e+05 6.12e+04 3.59e+05  -1.0 1.14e+06    -  1.71e-03 2.08e-01h  1
  79  2.1262940e+05 6.07e+04 5.40e+05  -1.0 1.16e+06    -  3.34e-01 8.75e-03h  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
  80  2.1272765e+05 6.07e+04 6.52e+05  -1.0 1.03e+06    -  1.04e-01 4.70e-04h  1
  81  2.2415572e+05 5.73e+04 1.06e+06  -1.0 1.00e+06    -  4.40e-01 5.50e-02h  2
  82  2.3463562e+05 5.45e+04 9.41e+05  -1.0 1.09e+06    -  1.94e-01 4.89e-02h  5
  83  2.4825352e+05 5.11e+04 7.95e+05  -1.0 1.17e+06    -  3.09e-01 6.19e-02h  5
  84  2.6876009e+05 4.89e+04 8.04e+05  -1.0 1.30e+06    -  1.11e-03 4.48e-02H  1
  85  2.7743158e+05 4.70e+04 7.44e+05  -1.0 1.21e+06    -  1.67e-04 3.80e-02h  1
  86  2.9957072e+05 4.25e+04 5.78e+05  -1.0 1.25e+06    -  8.33e-03 9.65e-02h  3
  87  3.5341744e+05 3.10e+04 3.18e+05  -1.0 1.08e+06    -  3.61e-02 2.69e-01H  1
  88  3.5845191e+05 2.65e+04 2.92e+05  -1.0 2.14e+05    -  1.97e-01 1.45e-01h  1
  89  1.5088996e+05 1.12e+04 1.89e+06  -1.0 1.06e+06    -  1.31e-01 5.79e-01F  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
  90  1.2557077e+05 1.04e+04 1.97e+06  -1.0 1.82e+06    -  4.03e-02 6.79e-02f  1
  91  1.2509047e+05 1.04e+04 1.98e+06  -1.0 1.37e+06    -  4.54e-06 1.19e-03f  1
  92  1.2526481e+05 1.04e+04 1.98e+06  -1.0 1.09e+05    -  1.56e-04 1.55e-03h  1
  93  1.2527575e+05 1.04e+04 1.98e+06  -1.0 1.11e+05    -  2.43e-03 9.54e-05h  1
  94  1.2530792e+05 1.04e+04 1.97e+06  -1.0 1.65e+05    -  2.96e-03 2.41e-04h  1
  95  1.2590033e+05 1.03e+04 1.97e+06  -1.0 1.33e+05    -  4.26e-03 4.70e-03h  1
  96  1.2605799e+05 1.03e+04 1.96e+06  -1.0 1.31e+05    -  9.38e-05 1.26e-03h  1
  97  1.2887468e+05 1.01e+04 1.92e+06  -1.0 1.14e+05    -  2.13e-03 2.36e-02h  1
  98  1.2905784e+05 1.01e+04 1.91e+06  -1.0 1.21e+05    -  5.99e-03 1.52e-03h  1
  99  1.3651965e+05 9.39e+03 2.63e+06  -1.0 1.18e+05    -  2.53e-03 6.23e-02h  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
 100  1.3858118e+05 9.21e+03 2.57e+06  -1.0 1.06e+05    -  1.18e-02 1.87e-02h  1
 101  1.4296639e+05 8.82e+03 2.48e+06  -1.0 1.05e+05    -  4.56e-02 4.03e-02h  1
 102  1.4301087e+05 8.82e+03 3.01e+06  -1.0 1.02e+05    -  2.26e-01 4.22e-04h  1
 103  1.4301009e+05 8.82e+03 9.94e+06  -1.0 7.10e+05    -  3.25e-02 1.03e-05f  1
 104  1.3902004e+05 8.64e+03 2.83e+06  -1.0 1.28e+06    -  1.90e-04 1.97e-02f  1
 105  1.4219397e+05 8.44e+03 5.25e+06  -1.0 2.09e+05    -  3.44e-06 2.24e-02h  1
 106  1.4889658e+05 8.07e+03 8.87e+06  -1.0 2.55e+05    -  2.97e-02 4.45e-02h  1
 107  1.6098257e+05 7.60e+03 1.48e+07  -1.0 4.67e+05    -  8.93e-02 6.10e-02h  1
 108  1.5780383e+05 7.49e+03 1.90e+08  -1.0 1.32e+06    -  4.01e-02 1.37e-02f  1
 109r 1.5780383e+05 7.49e+03 1.00e+03   3.3 0.00e+00    -  0.00e+00 3.65e-07R  7
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
 110r 1.5764509e+05 7.13e+03 6.40e+04   3.3 2.80e+05    -  2.44e-02 8.87e-03f  1
 111  1.5795418e+05 6.98e+03 5.77e+01  -1.0 5.38e+04    -  2.48e-02 2.10e-02h  1
 112  1.5797208e+05 6.98e+03 1.83e+02  -1.0 5.27e+04    -  2.40e-02 3.19e-04h  1
 113  1.5803844e+05 6.97e+03 6.56e+04  -1.0 8.97e+04    -  2.58e-01 9.43e-04h  1
 114  1.6678352e+05 6.34e+03 5.91e+04  -1.0 8.97e+04    -  2.93e-01 1.28e-01h  1
 115  1.6686395e+05 6.33e+03 5.26e+04  -1.0 7.60e+04    -  1.21e-01 1.43e-03h  1
 116  1.6687203e+05 6.33e+03 7.26e+04  -1.0 1.73e+05    -  3.17e-03 6.78e-05h  1
 117  1.6700141e+05 6.32e+03 7.25e+04  -1.0 1.96e+05    -  1.26e-03 1.27e-03h  2
 118  1.6706516e+05 6.32e+03 6.94e+04  -1.0 6.20e+05    -  8.17e-04 3.82e-04h  3
 119  1.6715642e+05 6.32e+03 5.59e+04  -1.0 1.07e+06    -  2.19e-03 3.29e-04h  3
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
 120  1.6722665e+05 6.31e+03 5.47e+04  -1.0 2.15e+06    -  5.94e-04 1.22e-04h  4
 121  1.6723902e+05 6.31e+03 2.59e+05  -1.0 5.25e+05    -  1.34e-02 4.99e-05h  1
 122  1.6746665e+05 6.31e+03 5.47e+05  -1.0 4.81e+05    -  2.38e-02 1.12e-03h  5
 123  1.6758171e+05 6.30e+03 9.82e+05  -1.0 4.30e+05    -  5.19e-02 7.44e-04h  6
 124  1.6758728e+05 6.30e+03 1.06e+06  -1.0 4.45e+05    -  5.86e-02 3.44e-05h 11
 125  1.6758993e+05 6.30e+03 1.08e+06  -1.0 4.45e+05    -  5.87e-02 1.64e-05h 12
 126  1.7294320e+05 6.09e+03 1.04e+06  -1.0 4.45e+05    -  3.32e-02 3.32e-02s 18
 127r 1.7294320e+05 6.09e+03 1.00e+03   3.0 0.00e+00  -2.0 0.00e+00 0.00e+00R  1
 128r 1.7267703e+05 5.50e+03 4.72e+03   3.0 3.33e+05    -  2.62e-02 1.25e-02f  1
 129  1.7687213e+05 5.11e+03 8.55e+01  -1.0 6.24e+04    -  2.13e-01 6.74e-02h  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
 130  1.7694922e+05 5.11e+03 8.20e+02  -1.0 6.15e+04    -  1.80e-01 1.42e-03h  1
 131  1.8092837e+05 4.77e+03 1.06e+04  -1.0 6.78e+04    -  4.46e-01 7.95e-02h  1
 132  1.8096502e+05 4.77e+03 6.86e+03  -1.0 6.13e+04    -  3.32e-01 8.57e-04h  1
 133  1.8122654e+05 4.76e+03 1.01e+05  -1.0 2.25e+05    -  2.87e-02 2.46e-03h  1
 134  1.8564136e+05 4.57e+03 3.25e+05  -1.0 2.32e+05    -  1.15e-01 4.09e-02h  1
 135  1.9516155e+05 4.20e+03 4.74e+05  -1.0 2.77e+05    -  1.57e-01 8.22e-02h  4
 136  1.9828459e+05 4.13e+03 1.88e+06  -1.0 5.69e+05    -  1.16e-01 1.75e-02h  3
 137  2.0093231e+05 4.09e+03 6.58e+06  -1.0 9.72e+05    -  8.19e-02 9.73e-03h  3
 138  2.0126541e+05 4.09e+03 1.57e+07  -1.0 4.72e+06    -  3.00e-03 2.89e-04h  4
 139  2.0142056e+05 4.09e+03 1.52e+08  -1.0 1.31e+07    -  3.11e-03 4.97e-05h  4
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
 140r 2.0142056e+05 4.09e+03 1.00e+03   1.4 0.00e+00    -  0.00e+00 3.37e-07R  7
 141r 2.0142218e+05 2.98e+03 1.00e+03   1.4 1.88e+04    -  2.87e-03 1.24e-03f  1
 142  2.0143358e+05 2.98e+03 1.73e+02  -1.0 4.31e+04    -  2.86e-02 3.56e-04h  1
 143  2.0144628e+05 2.97e+03 1.11e+04  -1.0 5.29e+04    -  3.73e-02 4.22e-04h  1
 144  2.0152748e+05 2.97e+03 2.84e+06  -1.0 2.84e+05    -  2.43e-01 7.81e-04h  1
 145  2.0619341e+05 2.85e+03 2.47e+06  -1.0 3.09e+05    -  2.37e-01 4.00e-02h  4
 146  2.0951386e+05 2.78e+03 2.46e+06  -1.0 3.53e+05    -  2.36e-01 2.65e-02h  6
 147  2.1391754e+05 2.69e+03 2.52e+06  -1.0 3.93e+05    -  9.31e-02 3.29e-02h  5
 148  2.1601572e+05 2.65e+03 2.80e+06  -1.0 4.91e+05    -  4.04e-02 1.34e-02h  4
 149  2.1800279e+05 2.62e+03 6.65e+06  -1.0 6.18e+05    -  1.24e-01 1.07e-02h  4
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
 150  2.1911794e+05 2.61e+03 1.20e+07  -1.0 1.09e+06    -  2.58e-02 3.73e-03h  4
 151  2.1921110e+05 2.61e+03 2.22e+08  -1.0 7.05e+06    -  6.58e-03 5.31e-05h  4
 152r 2.1921110e+05 2.61e+03 1.00e+03   0.8 0.00e+00    -  0.00e+00 3.47e-07R  9
 153r 2.1920807e+05 1.05e+03 9.97e+02   0.8 3.12e+04    -  2.84e-03 1.09e-03f  1
 154  2.1920994e+05 1.05e+03 8.77e+02  -1.0 6.13e+04    -  3.70e-02 1.09e-04h  1
 155  2.1921866e+05 1.04e+03 2.86e+04  -1.0 7.02e+04    -  6.17e-02 4.80e-04h  1
 156  2.1935917e+05 1.04e+03 1.88e+05  -1.0 1.89e+05    -  9.20e-03 1.34e-03h  1
 157  2.2047205e+05 1.03e+03 5.99e+05  -1.0 2.97e+05    -  2.24e-02 9.35e-03h  1
 158  2.2322883e+05 1.00e+03 1.06e+07  -1.0 2.29e+05    -  3.85e-01 3.16e-02h  2
 159  2.2786400e+05 9.50e+02 1.01e+07  -1.0 1.87e+05    -  4.84e-02 5.42e-02h  2
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
 160  2.3657417e+05 8.52e+02 4.64e+06  -1.0 1.58e+05    -  4.59e-01 1.15e-01h  4
 161  2.5533866e+05 6.96e+02 5.06e+06  -1.0 1.04e+05    -  1.07e-01 2.98e-01h  2
 162  2.7232586e+05 4.73e+01 1.09e+08  -1.0 2.36e+04  -2.5 3.03e-02 7.62e-01h  1
 163  2.6900408e+05 5.89e+01 1.02e+08  -1.0 3.09e+05  -3.0 6.59e-05 6.98e-02f  1
 164  2.6900426e+05 5.89e+01 4.73e+08  -1.0 5.04e+03   2.0 4.86e-02 3.68e-05h  1
 165  2.6909458e+05 5.78e+01 8.01e+09  -1.0 5.13e+03   1.5 8.94e-01 1.88e-02h  1
 166  2.6909495e+05 5.78e+01 9.26e+09  -1.0 2.37e+04   1.0 1.40e-02 1.98e-04h  1
 167r 2.6909495e+05 5.78e+01 1.00e+03   1.0 0.00e+00   1.5 0.00e+00 2.63e-07R  4
 168r 2.6909238e+05 5.72e+01 9.98e+02   1.0 4.35e+04    -  1.50e-03 1.19e-03f  1
 169  2.6909001e+05 5.72e+01 1.28e+01  -1.0 1.10e+05    -  6.92e-04 9.10e-05f  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
 170  2.6908843e+05 5.72e+01 8.01e+03  -1.0 5.35e+04    -  3.86e-02 2.57e-04f  1
 171  2.6909676e+05 5.72e+01 5.63e+04  -1.0 8.96e+04    -  2.97e-02 3.43e-04h  1
 172  2.6981660e+05 5.56e+01 1.11e+06  -1.0 9.26e+04    -  6.95e-01 2.75e-02h  1
 173  2.6981668e+05 5.56e+01 4.78e+08  -1.0 5.26e+03   1.0 5.79e-03 1.38e-05h  1
 174r 2.6981668e+05 5.56e+01 1.00e+03   0.7 0.00e+00   0.5 0.00e+00 4.56e-07R 10
 175r 2.6981543e+05 5.36e+01 1.01e+03   0.7 7.75e+03    -  1.43e-03 2.48e-03f  1
 176  2.6981276e+05 5.36e+01 1.42e+01  -1.0 1.11e+05    -  8.35e-04 1.00e-04f  1
 177  2.6981158e+05 5.36e+01 1.49e+05  -1.0 5.11e+04    -  6.29e-01 2.92e-04f  1
 178  2.7002156e+05 5.32e+01 2.73e+05  -1.0 9.73e+04    -  1.08e-01 7.32e-03h  1
 179  2.7648347e+05 3.97e+01 7.02e+05  -1.0 9.69e+04    -  6.95e-01 2.24e-01H  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
 180  3.0483323e+05 6.63e+00 4.37e+05  -1.0 8.30e+04    -  1.18e-01 1.00e+00H  1
 181  3.0179103e+05 3.87e+00 1.38e+05  -1.0 1.38e+04    -  6.84e-01 1.00e+00f  1
 182  2.9676419e+05 4.28e+00 3.17e+04  -1.0 2.30e+04    -  5.96e-01 1.00e+00f  1
 183  2.9580476e+05 5.30e+00 1.68e+05  -1.0 4.92e+04    -  9.55e-01 9.53e-02f  4
 184  2.9471482e+05 6.43e+00 1.53e+05  -1.0 4.80e+04    -  3.22e-01 1.13e-01f  4
 185  2.9356666e+05 7.44e+00 1.62e+05  -1.0 4.71e+04    -  9.59e-01 1.25e-01f  4
 186  2.9248608e+05 8.06e+00 1.47e+05  -1.0 4.59e+04    -  3.97e-01 1.25e-01f  4
 187  2.9148465e+05 8.35e+00 1.55e+05  -1.0 4.40e+04    -  1.00e+00 1.25e-01f  4
 188  2.8411311e+05 6.68e+01 5.02e+04  -1.0 4.19e+04    -  5.18e-01 1.00e+00f  1
 189  2.8411315e+05 6.68e+01 1.45e+10  -1.0 1.71e+03   0.0 1.00e+00 7.58e-05h  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
 190  2.8431586e+05 6.69e+01 1.40e+10  -1.0 8.59e+05    -  2.95e-02 2.18e-03h  6
 191  2.8550182e+05 6.77e+01 8.69e+09  -1.0 2.14e+05    -  3.81e-01 4.32e-02h  4
 192  2.9244683e+05 5.69e+01 6.37e+08  -1.0 7.96e+04    -  9.27e-01 5.00e-01h  2
 193  2.8933019e+05 9.78e+00 4.78e+10  -1.0 1.85e+04  -0.4 1.21e-02 1.00e+00f  1
 194  2.8932087e+05 9.77e+00 4.77e+10  -1.0 2.32e+05  -0.9 6.56e-03 3.14e-04f  1
 195  2.8669790e+05 1.20e+01 1.16e+10  -1.0 1.27e+04  -0.5 4.52e-05 1.00e+00f  1
 196  2.8659568e+05 1.73e-01 2.41e+07  -1.0 5.32e+02  -1.0 8.33e-01 1.00e+00f  1
 197  2.8659422e+05 2.82e-05 1.55e+04  -1.0 4.07e+00  -1.5 9.71e-01 1.00e+00f  1
 198  2.8658968e+05 4.41e-05 1.74e+03  -1.0 1.33e+01  -1.9 7.52e-01 1.00e+00f  1
 199  2.8657518e+05 1.01e-02 2.72e-01  -1.0 4.54e+01  -2.4 1.00e+00 1.00e+00f  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
 200  2.8289737e+05 2.81e+00 1.83e+03  -1.0 2.38e+07    -  1.43e-02 5.60e-04f  1
 201  2.8281029e+05 2.81e+00 1.68e+05  -1.0 1.41e+06    -  1.68e-01 7.93e-04f  1
 202  2.8006701e+05 1.41e+02 3.59e+05  -1.0 1.19e+06    -  2.95e-01 5.51e-02f  1
 203  2.8006884e+05 1.40e+02 7.79e+07  -1.0 9.29e+02  -2.0 1.00e+00 5.28e-03h  1
 204  2.8015019e+05 1.39e+02 7.73e+07  -1.0 7.90e+04  -2.5 8.06e-03 8.35e-03h  2
 205  2.8064274e+05 1.34e+02 1.05e+08  -1.0 8.16e+04  -2.9 7.51e-02 3.57e-02h  1
 206  2.8064278e+05 1.34e+02 4.03e+11  -1.0 8.64e+02   2.0 1.00e+00 3.23e-04h  1
 207  2.8064335e+05 1.34e+02 4.30e+11  -1.0 5.43e+04   2.4 2.35e-04 2.94e-05h  5
 208  2.8064399e+05 1.34e+02 4.40e+11  -1.0 5.85e+04   2.0 2.47e-04 3.03e-05h  5
 209  2.8064552e+05 1.34e+02 4.54e+11  -1.0 6.58e+04   1.5 9.02e-04 6.77e-05h  4
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
 210  2.8222241e+05 1.24e+02 3.97e+11  -1.0 9.40e+04    -  1.24e-01 7.34e-02h  1
 211  2.8220445e+05 1.24e+02 3.93e+11  -1.0 9.07e+04   1.0 1.52e-03 7.58e-04f  1
 212r 2.8220445e+05 1.24e+02 1.00e+03   1.8 0.00e+00   5.9 0.00e+00 3.67e-07R  5
 213r 2.8220129e+05 2.03e+01 1.38e+04   1.8 7.36e+04    -  5.97e-03 1.70e-03f  1
 214  2.8216015e+05 2.03e+01 3.00e+00  -1.0 1.24e+05    -  2.25e-03 1.12e-03f  1
 215  2.8215891e+05 2.03e+01 5.34e+04  -1.0 8.34e+04    -  3.16e-01 6.13e-05f  1
 216  2.8209715e+05 2.02e+01 2.17e+05  -1.0 8.68e+04    -  7.12e-01 3.18e-03f  1
 217  2.8285849e+05 1.94e+01 3.61e+05  -1.0 8.46e+04    -  1.39e-01 3.95e-02h  1
 218  2.8931606e+05 1.27e+01 7.06e+05  -1.0 8.25e+04    -  7.24e-01 3.44e-01h  1
 219  3.0346405e+05 1.81e+01 3.18e+05  -1.0 6.22e+04    -  1.67e-01 1.00e+00h  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
 220  3.0474704e+05 2.29e+00 1.55e+05  -1.0 5.63e+03    -  2.22e-01 1.00e+00h  1
 221  3.0400748e+05 1.53e+00 4.24e+04  -1.0 3.34e+03    -  6.64e-01 1.00e+00f  1
 222  3.0170824e+05 6.32e-01 7.78e+03  -1.0 1.04e+04    -  3.95e-01 1.00e+00f  1
 223  2.9693737e+05 2.81e+01 1.11e+04  -1.0 2.19e+04    -  9.83e-01 1.00e+00f  1
 224  2.9693737e+05 2.81e+01 1.69e+10  -1.0 2.42e+01   5.5 9.94e-01 3.29e-05h  1
 225  2.9693737e+05 2.81e+01 1.79e+13  -1.0 2.39e+02   5.0 1.00e+00 3.45e-05h  1
 226  2.9937267e+05 2.21e+00 1.79e+11  -1.0 7.59e+03    -  9.90e-01 1.00e+00h  1
 227  2.9716454e+05 3.10e+01 1.66e+15  -1.0 1.60e+04   4.5 4.83e-05 4.54e-01f  1
 228  2.9716640e+05 3.10e+01 1.66e+15  -1.0 7.66e+04    -  2.24e-06 7.62e-05h 14
 229  2.9716796e+05 3.10e+01 1.66e+15  -1.0 2.18e+06    -  6.70e-02 3.24e-06H  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
 230  2.9715453e+05 3.04e+01 1.63e+15  -1.0 3.23e+03   4.0 4.11e-01 1.93e-02f  1
 231  2.9718942e+05 3.03e+01 2.40e+15  -1.0 2.72e+04   3.6 1.00e+00 5.65e-03h  1
 232  3.0357797e+05 4.86e+00 2.98e+14  -1.0 2.80e+04   3.1 6.51e-01 1.00e+00h  1
 233  3.0357797e+05 4.86e+00 2.98e+14  -1.0 2.51e+01  12.9 5.51e-02 3.60e-04h  9
 234  3.0357797e+05 4.86e+00 2.98e+14  -1.0 8.54e+01  12.4 2.19e-02 9.33e-05h 10
 235  2.4711830e+05 3.19e+02 2.26e+14  -1.0 1.43e+05    -  9.69e-01 1.00e+00H  1
 236  2.4827390e+05 3.12e+02 2.21e+14  -1.0 2.01e+05    -  1.00e+00 2.38e-02h  1
 237  2.6037627e+05 2.53e+02 1.76e+14  -1.0 2.00e+05    -  1.00e+00 2.50e-01h  3
 238  2.6037627e+05 2.54e+02 1.77e+14  -1.0 6.29e+01  12.9 2.35e-02 2.73e-03h  6
 239  2.6430151e+05 1.21e+01 2.92e+12  -1.0 1.88e+04    -  1.00e+00 1.00e+00h  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
 240  2.7611279e+05 8.75e+01 9.74e+12  -1.0 9.24e+04    -  9.56e-01 5.00e-01h  2
 241  2.9333225e+05 4.81e+01 7.71e+12  -1.0 7.76e+04    -  6.87e-02 1.00e+00H  1
 242r 2.9333225e+05 4.81e+01 1.00e+03   0.9 0.00e+00  12.4 0.00e+00 7.39e-09R  2
 243r 2.9333613e+05 4.77e+01 1.26e+04   0.9 1.53e+04    -  1.43e-02 1.16e-03f  1
 244  2.9333219e+05 4.77e+01 7.00e+00  -1.0 1.37e+05    -  4.04e-04 1.01e-04f  1
 245  2.9332573e+05 4.77e+01 1.21e+05  -1.0 8.47e+04    -  5.21e-01 3.63e-04f  1
 246  2.9202097e+05 4.53e+01 1.15e+05  -1.0 1.29e+05    -  4.51e-02 4.74e-02f  2
 247  2.9143485e+05 4.41e+01 1.40e+05  -1.0 1.15e+05    -  1.50e-01 2.50e-02f  3
 248  2.9080870e+05 4.28e+01 1.55e+05  -1.0 1.10e+05    -  1.02e-01 2.88e-02f  3
 249  2.9017179e+05 4.13e+01 3.44e+05  -1.0 9.62e+04    -  6.03e-01 3.56e-02f  3
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
 250  2.8985394e+05 4.05e+01 3.52e+05  -1.0 1.01e+05    -  6.52e-02 1.84e-02f  4
 251  2.8739410e+05 8.34e+01 4.67e+05  -1.0 8.26e+04    -  6.84e-01 1.90e-01f  1
 252  2.8739410e+05 8.34e+01 1.79e+09  -1.0 6.96e+01  11.9 1.84e-01 3.12e-05h  1
 253r 2.8739410e+05 8.34e+01 1.00e+03   1.9 0.00e+00  11.4 0.00e+00 1.56e-07R  2
 254r 2.8739740e+05 3.23e+01 1.65e+04   1.9 3.82e+04    -  6.90e-03 1.66e-03f  1
 255  2.8736484e+05 3.23e+01 1.25e+00  -1.0 1.42e+05    -  9.40e-04 8.12e-04f  1
 256  2.8720051e+05 3.21e+01 7.11e+03  -1.0 9.99e+04    -  1.22e-01 5.46e-03f  1
 257  2.8719406e+05 3.21e+01 1.94e+05  -1.0 8.73e+04    -  4.69e-01 2.16e-04f  1
 258  2.8417159e+05 2.87e+01 1.94e+05  -1.0 1.35e+05    -  1.13e-01 7.18e-02f  1
 259r 2.8417159e+05 2.87e+01 1.00e+03   1.4 0.00e+00  11.0 0.00e+00 4.73e-07R  4
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
 260r 2.8416979e+05 2.86e+01 9.97e+02   1.4 1.57e+04    -  2.50e-03 1.47e-03f  1
 261  2.8414991e+05 2.86e+01 1.89e+00  -1.0 1.28e+05    -  7.81e-04 5.31e-04f  1
 262  2.8413550e+05 2.86e+01 3.89e+03  -1.0 8.07e+04    -  2.30e-02 7.41e-04f  1
 263  2.8411984e+05 2.85e+01 7.36e+03  -1.0 7.88e+04    -  1.72e-02 7.90e-04f  1
 264  2.8412882e+05 2.85e+01 1.12e+06  -1.0 4.83e+04    -  7.25e-01 1.01e-03h  1
 265  2.8660718e+05 2.40e+01 9.41e+05  -1.0 6.83e+04    -  1.80e-01 1.57e-01h  3
 266  2.9650411e+05 9.26e+00 3.76e+05  -1.0 6.22e+04    -  7.72e-01 6.14e-01H  1
 267  3.0368460e+05 2.10e+00 2.26e+05  -1.0 3.04e+04    -  1.27e-01 1.00e+00H  1
 268  3.0051784e+05 2.23e+00 1.50e+05  -1.0 1.43e+04    -  3.94e-01 1.00e+00f  1
 269  2.9540297e+05 1.76e+00 3.42e+04  -1.0 2.36e+04    -  3.24e-01 1.00e+00F  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
 270  2.9540297e+05 1.76e+00 3.86e+08  -1.0 8.06e+00  10.5 7.86e-05 1.57e-03h  1
 271  2.9540297e+05 1.76e+00 3.87e+08  -1.0 8.05e+00  10.0 1.64e-03 1.57e-05h  1
 272r 2.9540297e+05 1.76e+00 1.00e+03   0.2 0.00e+00   9.5 0.00e+00 9.08e-08R  2
 273r 2.9540344e+05 4.13e-01 1.73e+03   0.2 1.13e+04    -  4.55e-03 1.00e-03f  1
 274  2.9540180e+05 4.13e-01 1.69e+04  -1.0 1.20e+05    -  2.17e-01 4.88e-05f  1
 275  2.9529371e+05 4.21e-01 1.13e+05  -1.0 8.26e+04    -  2.19e-01 6.33e-03f  1
 276  2.7222296e+05 3.33e+02 2.62e+05  -1.0 9.50e+04    -  2.06e-01 1.00e+00F  1
 277  2.7172564e+05 2.82e+02 2.40e+05  -1.0 3.52e+04    -  5.42e-01 8.69e-02f  1
 278  2.7003695e+05 2.56e+02 1.68e+05  -1.0 2.78e+04    -  7.46e-01 4.36e-01f  1
 279r 2.7003695e+05 2.56e+02 1.00e+03   2.4 0.00e+00   9.1 0.00e+00 4.76e-07R  3
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
 280r 2.7004490e+05 1.60e+02 3.83e+04   2.4 9.18e+04    -  1.13e-02 2.12e-03f  1
 281  2.6994022e+05 1.59e+02 1.42e+00  -1.0 1.13e+05    -  2.94e-03 3.10e-03f  1
 282  2.6993730e+05 1.59e+02 9.49e+03  -1.0 8.36e+04    -  2.32e-01 1.09e-04f  1
 283  2.6954764e+05 1.57e+02 3.34e+04  -1.0 8.59e+04    -  4.99e-01 1.34e-02f  1
 284  2.6948270e+05 1.57e+02 4.32e+05  -1.0 1.77e+05    -  5.12e-01 1.91e-03f  1
 285  2.6681167e+05 1.43e+02 4.27e+05  -1.0 1.80e+05    -  1.61e-01 8.16e-02f  1
 286r 2.6681167e+05 1.43e+02 1.00e+03   2.2 0.00e+00   8.6 0.00e+00 4.99e-07R  3
 287r 2.6680781e+05 8.51e+00 9.96e+02   2.2 2.43e+04    -  5.65e-03 5.84e-03f  1
 288  2.6657756e+05 8.46e+00 6.83e+00  -1.0 1.00e+05    -  3.03e-02 7.31e-03f  1
 289  2.6657463e+05 8.45e+00 1.21e+04  -1.0 7.95e+04    -  1.51e-01 1.27e-04f  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
 290  2.6649023e+05 8.42e+00 1.24e+04  -1.0 7.03e+04    -  7.83e-03 4.01e-03f  1
 291  2.6638786e+05 8.35e+00 7.77e+04  -1.0 5.44e+04    -  3.74e-01 8.53e-03f  1
 292  2.6641247e+05 8.34e+00 4.95e+05  -1.0 8.17e+04    -  3.42e-01 1.34e-03h  1
 293  2.6895978e+05 7.68e+00 6.89e+05  -1.0 9.10e+04    -  6.11e-01 1.25e-01h  4
 294  2.7128721e+05 7.65e+00 6.12e+05  -1.0 8.99e+04    -  2.79e-01 1.15e-01h  4
 295  2.7376815e+05 7.61e+00 5.65e+05  -1.0 8.83e+04    -  4.82e-01 1.25e-01h  4
 296  2.7618467e+05 7.45e+00 5.61e+05  -1.0 8.58e+04    -  6.72e-01 1.25e-01h  4
 297  2.7851781e+05 7.21e+00 4.96e+05  -1.0 8.27e+04    -  1.73e-01 1.25e-01h  4
 298  2.8298300e+05 8.16e+00 4.65e+05  -1.0 7.90e+04    -  8.31e-01 2.50e-01h  3
 299  2.8398247e+05 7.77e+00 4.53e+05  -1.0 7.06e+04    -  1.74e-01 6.25e-02h  5
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
 300  2.8410295e+05 7.71e+00 5.82e+05  -1.0 6.80e+04    -  9.09e-01 7.81e-03h  8
 301  2.8411793e+05 7.70e+00 5.84e+05  -1.0 6.76e+04    -  1.87e-01 9.77e-04h 11
 302  2.8411981e+05 7.70e+00 5.97e+05  -1.0 6.76e+04    -  9.96e-01 1.22e-04h 14
 303  2.9945684e+05 2.93e+01 2.41e+05  -1.0 6.76e+04    -  1.81e-01 1.00e+00w  1
 304  3.0340995e+05 2.22e+00 2.62e+04  -1.0 1.68e+04    -  1.00e+00 1.00e+00w  1
 305  2.9827244e+05 3.31e+00 7.99e+04  -1.0 2.36e+04    -  4.02e-01 1.00e+00w  1
 306  2.8412027e+05 7.70e+00 5.97e+05  -1.0 3.93e+04    -  1.81e-01 3.05e-05h 15
 307  3.0354204e+05 1.23e+01 2.89e+05  -1.0 6.76e+04    -  1.00e+00 1.00e+00H  1
 308  3.0149455e+05 2.28e+00 1.62e+05  -1.0 9.49e+03    -  3.32e-01 1.00e+00f  1
 309  2.9665499e+05 6.16e+00 1.32e+04  -1.0 2.23e+04    -  1.00e+00 1.00e+00f  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
 310  2.9343608e+05 2.56e+01 1.71e+04  -1.0 7.76e+04    -  1.61e-01 2.06e-01f  2
 311  2.9343608e+05 2.56e+01 1.84e+09  -1.0 1.49e+01   8.1 1.00e+00 2.87e-04h  1
 312  2.9317468e+05 8.50e+00 8.12e+07  -1.0 2.97e+03    -  9.56e-01 1.00e+00f  1
 313  2.8944359e+05 2.11e+00 2.10e+06  -1.0 1.68e+04    -  9.95e-01 1.00e+00f  1
 314  2.8918867e+05 2.17e-02 2.73e+03  -1.0 1.31e+03    -  1.00e+00 1.00e+00f  1
 315  2.8319976e+05 5.42e+01 3.18e+04  -1.0 3.26e+04    -  8.80e-01 1.00e+00f  1
 316  2.8319976e+05 5.42e+01 1.35e+10  -1.0 1.46e+01   7.6 1.00e+00 3.19e-05h  1
 317  2.8594547e+05 8.26e+00 1.33e+08  -1.0 1.32e+04    -  9.90e-01 1.00e+00h  1
 318  2.8595448e+05 6.08e-01 1.99e+14  -1.0 1.32e+02   7.1 6.73e-07 1.00e+00h  1
 319  2.8595449e+05 1.61e-04 8.82e+09  -1.0 7.07e-01   6.7 9.40e-01 1.00e+00h  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
 320  2.8595471e+05 1.65e-07 1.40e+05  -1.0 1.12e+00    -  9.91e-01 1.00e+00h  1
 321  2.8595471e+05 1.04e-10 8.05e+01  -1.0 1.05e-07   6.2 9.95e-01 1.00e+00h  1
 322  2.8381914e+05 4.99e-01 3.55e+03  -1.0 1.42e+08    -  3.10e-03 6.84e-05f  1
 323  2.8066086e+05 4.59e+01 7.36e+03  -1.0 9.09e+06    -  6.59e-03 3.23e-03f  1
 324  2.7668880e+05 9.00e+01 3.96e+04  -1.0 3.97e+06    -  4.45e-02 1.14e-02f  1
 325  2.7668880e+05 9.00e+01 1.67e+09  -1.0 8.95e+01   5.7 1.00e+00 1.14e-05h  1
 326  2.8191331e+05 4.53e+01 1.64e+07  -1.0 4.18e+04    -  9.90e-01 5.00e-01h  2
 327  2.8544472e+05 3.47e+00 3.02e+04  -1.0 1.15e+04    -  1.00e+00 1.00e+00h  1
 328  2.8228282e+05 2.38e+01 6.58e+04  -1.0 4.78e+04    -  7.35e-01 5.00e-01f  2
 329  2.8311865e+05 4.27e+00 3.39e+03  -1.0 1.16e+04    -  1.00e+00 1.00e+00h  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
 330  2.8247002e+05 8.36e-01 1.84e+01  -1.0 3.99e+03    -  1.00e+00 1.00e+00f  1
 331  2.8251898e+05 4.93e-03 4.89e-01  -1.7 3.96e+02    -  1.00e+00 1.00e+00h  1
 332  2.8251870e+05 1.50e-07 1.85e-05  -3.8 1.13e+00    -  1.00e+00 1.00e+00f  1
 333  2.8251869e+05 7.46e-11 7.78e-10  -8.6 1.49e-03    -  1.00e+00 1.00e+00h  1

Number of Iterations....: 333

                                   (scaled)                 (unscaled)
Objective...............:   2.8251869477498095e+05    2.8251869477498095e+05
Dual infeasibility......:   7.7843619785268429e-10    7.7843619785268429e-10
Constraint violation....:   1.3128149817982369e-11    7.4578565545380116e-11
Complementarity.........:   2.5072731634536451e-09    2.5072731634536451e-09
Overall NLP error.......:   4.0904109550221068e-11    2.5072731634536451e-09


Number of objective function evaluations             = 1045
Number of objective gradient evaluations             = 311
Number of equality constraint evaluations            = 1049
Number of inequality constraint evaluations          = 1049
Number of equality constraint Jacobian evaluations   = 349
Number of inequality constraint Jacobian evaluations = 349
Number of Lagrangian Hessian evaluations             = 333
Total CPU secs in IPOPT (w/o function evaluations)   =      0.411
Total CPU secs in NLP function evaluations           =      0.037

EXIT: Optimal Solution Found.

Step 3: Test the Byproduct Recovery Framework#

Now that the model is solved, the next task is to calculate the cost and evaluate economic feasibility.

3.1. Specify Product Prices

Product prices are defined in costing_dictionaries.py. Users can access the default sale prices via load_default_sale_prices() function, as shown below:

sale_prices = load_default_sale_prices()
Li_price = sale_prices["Li"]
Co_price = sale_prices["Co"]

Alternatively, users may specify custom sale prices by manually replacing the right-hand side values of the price expressions.

These prices will be used to compute annual revenue, which is a key input to the byproduct recovery decision framework.

3.2. Introduce the Framework and Specify the Product Outputs

Next, introduce the byproduct recovery framework and specify the target products recovered from the diafiltration process.

The byproduct recovery framework accepts user inputs, where products are listed in a structure called material_list, and their associated data (e.g. flow rate, price) are organized in a dictionary called material_data.

  • material_list: A list of product names (strings).

  • material_data: A dictionary where each key corresponds to a product name and maps to its properties such as flow rate and price.

This structured input will be passed into the byproduct recovery decision framework to assess economic viability.

# The framework take user input
material_list = ["Lithium", "Cobalt"]

# Introduce the byproduct recovery framework
model = ConcreteModel()
model.recovery_determine = ByproductRecovery(materials=material_list)

# Define input values based on provided materials
material_data = {
    "Lithium": {
        "production": Li_recovery_mass,
        "market_value": Li_price,
        "waste_disposal": 1,
        "conversion": 0,
        "conversion_cost": 0,
        "process_steps": 1,
        "process_cost": total_annualized_cost,
    },
    "Cobalt": {
        "production": Co_recovery_mass,
        "market_value": Co_price,
        "waste_disposal": 1,
        "conversion": 0,
        "conversion_cost": 0,
        "process_steps": 0,
        "process_cost": 0,
    },
}

3.3. Set Additional Parameters and Evaluate Net Benefit

To evaluate the economic feasibility, we must define additional parameters for each product:

  • "waste_disposal": Set to 1 to indicate that waste disposal costs are considered.

  • "conversion": Set to 0 if no conversion process is required to recover the material.

  • "conversion_cost": Set to 0 when conversion is not needed.

  • "process_steps": Set to 0 if no additional steps are needed beyond the current recovery process.

In this case, the lithium–cobalt diafiltration plant recovers both lithium and cobalt in a single process. No additional purification or recovery steps are considered for either product. As such:

  • The process cost is only accounted for once under "Lithium" production (though it could alternatively be placed under "Cobalt" with no impact on results).

  • Both products are assumed to be sold at market prices, regardless of purity level.

# Set values based on material list
for m in material_list:
    data = material_data.get(m, {})
    model.recovery_determine.material_production[m].set_value(data.get("production", 0))
    model.recovery_determine.market_value[m].set_value(data.get("market_value", 0))
    model.recovery_determine.waste_disposal_cost[m].set_value(
        data.get("waste_disposal", 0)
    )
    model.recovery_determine.conversion_possible[m].set_value(data.get("conversion", 0))
    model.recovery_determine.conversion_cost[m].set_value(
        data.get("conversion_cost", 0)
    )
    model.recovery_determine.added_process_steps[m].set_value(
        data.get("process_steps", 0)
    )
    model.recovery_determine.added_process_cost[m].set_value(
        data.get("process_cost", 0)
    )

💡 Note: The 0 in data.get("production", 0) does not mean zero production. It indicates that the production rate is assumed to be steady-state (i.e., constant over time), not time-varying.

3.4. Calculate the Overall Net Benefit

With parameters such as production rate, market price, and associated costs specified for each product, the byproduct recovery framework can now be implemented to quantify the overall net benefit.

The overall net benefit is used to determine profitability:

  • If net_benefit_value > 0 → The byproduct recovery process is profitable.

  • If net_benefit_value ≤ 0 → The process is not profitable.

potential_revenue = value(model.recovery_determine.potential_revenue)
assert potential_revenue >= 0, "Potential revenue should be non-negative."

determine_result = model.recovery_determine.determine_financial_viability()
assert isinstance(
    determine_result, str
), f"Expected a string message, but got {type(determine_result)}"

net_benefit_value = value(model.recovery_determine.net_benefit)
assert net_benefit_value == pytest.approx(320373532.81, rel=1e-4)

# Check the output string for financial viability
print("\n--- Byproduct Recovery Decision ---")
print(determine_result)
--- Byproduct Recovery Decision ---
✅ Byproduct recovery is financially viable. Net Benefit: 320342254.82 $/yr

Note: The assert statements are included to verify that the model is built as expected.
They are helpful for testing and debugging, but not required for using the byproduct recovery framework.

Package Installation#

As mentioned previously, Pyomo, IDAES, and PrOMMiS packages are necessary to use the framework. If these packages are not installed, this may be done using the following commands in Anaconda Prompt:

pip install pyomo

pip install idaes-pse

For more detailed installation instructions, refer to the respective README.md files for Pyomo, IDAES, and ProMMiS.