.. _tutorial_optimization_label: Thermal Power Plant Efficiency Optimization ------------------------------------------- Task ^^^^ Designing a power plant meets multiple different tasks, such as finding the optimal fresh steam temperature and pressure to reduce exhaust steam water content, or the optimization of extraction pressures to maximize cycle efficiency and many more. In case of a rather simple power plant topologies the task of finding optimized values for e.g. extraction pressures is still manageable without any optimization tool. As the topology becomes more complex and boundary conditions come into play the usage of additional tools is recommended. The following tutorial is intended to show the usage of pymoo in combination with TESPy to **maximize the cycle efficiency of a power plant with two** **extractions.** You can download the code here: :download:`optimization_example.py ` .. figure:: /_static/images/tutorials/optimization/flowsheet.svg :align: center :alt: Topology of the power plant :figclass: only-light Figure: Topology of the power plant .. figure:: /_static/images/tutorials/optimization/flowsheet_darkmode.svg :align: center :alt: Topology of the power plant :figclass: only-dark Figure: Topology of the power plant What is pymoo? ^^^^^^^^^^^^^^ `pymoo `__ ( Multi-objective Optimization in Python, :cite:`pymoo`) is a library that provides numerous optimization algorithms. pymoo can be used to solve constrained, unconstrained, single objective and multi objective problems. In this example we will use an evolutionary algorithm to find the optimal pressure values. Evolutionary Algorithms +++++++++++++++++++++++ Evolutionary Algorithms (EA) are optimization algorithms inspired by biological evolution. In a given population the algorithm uses the so-called fitness function to determine the quality of the solutions to each individual (set of decision variables) problem. The best possible solution of the population is called champion. Via mutation, recombination and selection your population evolves to find better solutions. EA will never find an exact solution to your problem. They can only give an approximation for the real optimum. Install pymoo +++++++++++++ Installation of pymoo is straight-forward: Just install tespy with the extra dependencies "opt", e.g. with pip .. code-block:: bash pip install tespy[opt] of uv .. code-block:: bash uv add tespy --extra opt Creating your TESPy-Model ^^^^^^^^^^^^^^^^^^^^^^^^^ We use the :py:class:`ModelTemplate ` base class, which provides parameter access, solving and optimization infrastructure automatically. Inheriting from it requires implementing three methods: - :code:`_create_network` - assembles the TESPy network and produces a stable initial solution. Always call :code:`super()._create_network()` first. - :code:`_parameter_lookup` - returns a :code:`dict` that maps human-readable parameter names to their location in the network. These names are used directly by the optimizer, :code:`get_parameter` and :code:`set_parameters`. - :code:`solve_model` - routes calls to the appropriate solve logic (e.g. :code:`solve_model_design` or custom logic). The :code:`_create_network` method below builds the power plant with two extraction turbines, sets boundary conditions and runs the initial design-point solve. .. dropdown:: Display source code for the SamplePlant class .. literalinclude:: /../tutorial/advanced/optimization_example.py :language: python :start-after: [sec_1] :end-before: [sec_2] Next, :code:`_parameter_lookup` registers lookup between model internals and keyword parameter specifications for inputs and outputs. Connection attributes using the :code:`["Connections", label, attr]` form, Component attributes follow the :code:`["Components", label, attr]` form. The thermal efficiency is registered as a read-only derived quantity via :code:`{"get": callable}`: .. math:: \eta_\text{th}=\frac{|\sum P|}{\dot{Q}_{sg}} The feasibility check inside :code:`calc_efficiency` returns :code:`np.nan` for non-converged or physically infeasible solutions, which the optimizer treats as a penalty automatically. .. dropdown:: Display source code for :code:`_parameter_lookup`, :code:`calc_efficiency` and :code:`solve_model` .. literalinclude:: /../tutorial/advanced/optimization_example.py :language: python :start-after: [sec_2] :end-before: [sec_3] After instantiating the model, all registered parameters are immediately accessible via :code:`get_parameter`: .. literalinclude:: /../tutorial/advanced/optimization_example.py :language: python :start-after: [sec_3] :end-before: [sec_4] .. attention:: The sense of optimization is minimization by default. We can change the sense for each of the objectives we pass to :py:meth:`optimize ` by passing a list with :code:`True` or :code:`False` for each individual objective **in identical order as the objectives** using the :code:`minimize_flags` argument. We set one inequality constraint - the first extraction pressure must exceed the second: .. math:: p_{e,1} > p_{e,2} This is expressed inside the :code:`constraints` dictionary by referencing the name of the first parameter as the lower bound of the second. The :code:`kpi` argument selects additional model outputs to include in the result log. Here we track the high-pressure turbine power and pressure ratio. Run pymoo-Optimization ^^^^^^^^^^^^^^^^^^^^^^ :py:meth:`model.optimize ` wraps :py:class:`OptimizationProblem ` and a pymoo algorithm into a single call and returns a :code:`DataFrame` of all evaluated individuals. For more information on available algorithms see the `list of algorithms `__. .. literalinclude:: /../tutorial/advanced/optimization_example.py :language: python :start-after: [sec_5] :end-before: [sec_6] In our run, we got the following optimal solution: .. code:: bash Efficiency: 44.82 % Extraction 1: 25.753 bar Extraction 2: 2.685 bar .. figure:: /_static/images/tutorials/optimization/optimization_result.svg :align: center :alt: Scatter plot for all individuals during the optimization :figclass: only-light Figure: Scatter plot for all individuals during the optimization .. figure:: /_static/images/tutorials/optimization/optimization_result_darkmode.svg :align: center :alt: Scatter plot for all individuals during the optimization :figclass: only-dark Figure: Scatter plot for all individuals during the optimization You can access the data generated by the optimization from the returned :code:`DataFrame`, which contains every evaluated individual. The plotting code in the download shows how to filter for feasible solutions and highlight the optimum. .. literalinclude:: /../tutorial/advanced/optimization_example.py :language: python :start-after: [sec_6] :end-before: [sec_7]