Funding for this research was provided by:
Conselho Nacional de Desenvolvimento Científico e Tecnológico (304508/2023-3)
Fundação de Amparo à Pesquisa do Estado de São Paulo (2014/50279-4)
Fundação de Amparo à Pesquisa do Estado de São Paulo (2020/15230-5)
Universidade De São Paulo
Article History
Received: 18 October 2025
Revised: 31 March 2026
Accepted: 6 April 2026
First Online: 8 May 2026
Declarations
:
: On behalf of all authors, the corresponding author states that there is no conflict of interest.
: Most of the software environment used in this work can be found in the Docker container provided by dolfin-adjoint (available in ). The tutorials presented there may also help with the implementation. In order to reproduce the results the following steps are needed: define a mesh; define the function spaces of the state variables ( u , p ); define the function space of the design variables ( ); define the boundary conditions; define the state equations (Navier–Stokes for incompressible flows); solve the state equations, which causes pyadjoint to annotate the steps in the tape; define the objective function; calculate the initial objective function value; start the optimization loop: solve the state equations for current ; calculate the current objective function value; call pyadjoint to mount and solve the adjoint model; pass the sensitivity to the optimizer ( scipy library); update the design variable ( ): if the convergence criteria is met return; else: restart the optimization loop;