How to explore a model with parameter sweep

Overview

This guide shows you how to use the parameter sweep tool to explore the effect of changing model parameters or decision variables within your WaterTAP model. This might be useful, for example, if you have an existing model of a multi-stage treatment train and you’d like to see the effect of varying Pump 1 pressure and Pump 2 pressure independently (where all possible combinations of Pump 1 and Pump 2 pressure will be explicitly tested). The type and quantity of parameters to be varied are easily changed following steps like the ones below.

How To

Begin by importing or explicitly programming any functions relating to the following steps:

  1. Building the Pyomo flowsheet model

  2. Simulating the model using an initial condition

  3. Setting up the optimization (e.g., unfixing and setting bounds)

  4. Performing the optimization

For example, the code below imports from an existing flowsheet module, RO with energy recovery. In general you would import your own flowsheet module.

# replace this with your own flowsheet module, e.g.
# import my_flowsheet_module as mfm
import watertap.examples.flowsheets.RO_with_energy_recovery.RO_with_energy_recovery as RO_flowsheet

Once this is done, import the parameter sweep tool

from watertap.tools.parameter_sweep import parameter_sweep, LinearSample

Conceptually, regardless of the number of iterations necessary to test each possible combination of variables, it is only necessary to build, simulate, and set up the model once. Thus, these steps are left to the user and handled outside the parameter sweep function. Depending on how the functions you’ve defined work, this could be as straightforward as

# replace these function calls with
# those in your own flowsheet module

# set up system
m = RO_flowsheet.build()
RO_flowsheet.set_operating_conditions(m)
RO_flowsheet.initialize_system(m)

# simulate
RO_flowsheet.solve(m)

# set up the model for optimization
RO_flowsheet.optimize_set_up(m)

where m is the flowsheet model that results after the initial “build” step and subsequent operations are performed on that object.

Once this sequence of setup steps is performed, the parameters to be varied should be identified with a dictionary:

sweep_params = dict()
sweep_params['Feed Mass NaCl'] = LinearSample(m.fs.feed.flow_mass_phase_comp[0, 'Liq', 'NaCl'], 0.005, 0.155, 4)
sweep_params['Water Recovery'] = LinearSample(m.fs.RO.recovery_mass_phase_comp[0, 'Liq', 'H2O'], 0.3, 0.7, 4)

where the basic pattern is dict_name['Short/Pretty-print Name'] = LinearSample(m.path.to.model.variable, lower_limit, upper_limit, num_samples). For example, “Feed Mass NaCl” (the feed mass flow rate of NaCl), which is accessed through the model variable m.fs.feed.flow_mass_phase_comp[0, 'Liq', 'NaCl'], is to be varied between 0.005 and 0.155 with 4 equally-spaced values, i.e., [0.005, 0.055, 0.105, 0.155]. It is also possible to perform random sampling (uniform or normal) with the parameter sweep tool, or the user can specify their own sampling method. In this case, the 2 parameters will each be varied across 4 values for a total of 16 combinations. Note that there is no limit on the number of sweep variables specified or their resolution besides the practical limit of how long it will take to optimize using each combination of parameters (e.g., if 5 different variables are provided and each one is individually represented with 20 discrete values, the total number of combinations is 20^5 = 3.2 million!).

After specifying the input parameters, the user should then specify output values on the flowsheet that will be reported in the summary CSV file, which has a similar format to the sweep parameters. For this RO flowsheet we’ll report the levelized cost of water, the optimized RO area, and the output pressure of pump 1:

outputs = dict()
outputs['RO membrane area'] = m.fs.RO.area
outputs['Pump 1 pressure'] = m.fs.P1.control_volume.properties_out[0].pressure
outputs['Levelized Cost of Water'] = m.fs.costing.LCOW

Once the problem is setup and the parameters are identified, the parameter_sweep function can finally be invoked which will perform the adjustment and optimization of the model using each combination of variables specified above and saving to results.csv (utilizing the solve method defined in our flowsheet module).

parameter_sweep(m, sweep_params, outputs, 'results.csv')

Note that there are additional keyword arguments that can be passed to this function if you desire more control or debugging outputs, especially with regard to the restart logic used after a previous optimization attempt has failed or with managing local outputs computed on parallel hardware. For more information, consult the technical reference for the parameter sweep tool.

Function Documentation

class watertap.tools.parameter_sweep.FixedSample(pyomo_object, *args, **kwargs)[source]
class watertap.tools.parameter_sweep.LatinHypercubeSample(pyomo_object, *args, **kwargs)[source]
class watertap.tools.parameter_sweep.LinearSample(pyomo_object, *args, **kwargs)[source]
class watertap.tools.parameter_sweep.NormalSample(pyomo_object, *args, **kwargs)[source]
class watertap.tools.parameter_sweep.RandomSample(pyomo_object, *args, **kwargs)[source]
class watertap.tools.parameter_sweep.SamplingType(value)[source]

An enumeration.

class watertap.tools.parameter_sweep.UniformSample(pyomo_object, *args, **kwargs)[source]
watertap.tools.parameter_sweep.parameter_sweep(model, sweep_params, outputs, results_file=None, optimize_function=<function _default_optimize>, optimize_kwargs=None, reinitialize_function=None, reinitialize_kwargs=None, mpi_comm=None, debugging_data_dir=None, interpolate_nan_outputs=False, num_samples=None, seed=None)[source]

This function offers a general way to perform repeated optimizations of a model for the purposes of exploring a parameter space while monitoring multiple outputs. If provided, writes single CSV file to results_file with all inputs and resulting outputs.

Parameters
  • model – A Pyomo ConcreteModel containing a watertap flowsheet, for best results it should be initialized before being passed to this function.

  • sweep_params – A dictionary containing the values to vary with the format sweep_params['Short/Pretty-print Name'] = (model.fs.variable_or_param[index], lower_limit, upper_limit, num_samples). A uniform number of samples num_samples will be take between the lower_limit and upper_limit.

  • outputs – A dictionary containing “short names” as keys and and Pyomo objects on model whose values to report as values. E.g., outputs['Short/Pretty-print Name'] = model.fs.variable_or_expression_to_report.

  • results_file (optional) – The path and file name where the results are to be saved; subdirectories will be created as needed.

  • optimize_function (optional) – A user-defined function to perform the optimization of flowsheet model and loads the results back into model. The first argument of this function is model. The default uses the default IDAES solver, raising an exception if the termination condition is not optimal.

  • optimize_kwargs (optional) – Dictionary of kwargs to pass into every call to optimize_function. The first arg will always be model, e.g., optimize_function(model, **optimize_kwargs). The default uses no kwargs.

  • reinitialize_function (optional) – A user-defined function to perform the re-initialize the flowsheet model if the first call to optimize_function fails for any reason. After reinitialize_function, the parameter sweep tool will immediately call optimize_function again.

  • reinitialize_kwargs (optional) – Dictionary or kwargs to pass into every call to reinitialize_function. The first arg will always be model, e.g., reinitialize_function(model, **reinitialize_kwargs). The default uses no kwargs.

  • mpi_comm (optional) – User-provided MPI communicator for parallel parameter sweeps. If None COMM_WORLD will be used. The default is sufficient for most users.

  • debugging_data_dir (optional) – Save results on a per-process basis for parallel debugging purposes. If None no debugging data will be saved.

  • interpolate_nan_outputs (optional) – When the parameter sweep has finished, interior values of np.nan will be replaced with a value obtained via a linear interpolation of their surrounding valid neighbors. If true, a second output file with the extension “_clean” will be saved alongside the raw (un-interpolated) values.

  • num_samples (optional) – If the user is using sampling techniques rather than a linear grid of values, they need to set the number of samples

  • seed (optional) – If the user is using a random sampling technique, this sets the seed

Returns

A list were the first N columns are the values of the parameters passed

by sweep_params and the remaining columns are the values of the simulation identified by the outputs argument.

Return type

save_data