diff --git a/src/OID_analysis/Li22b.md b/src/OID_analysis/Li22b.md new file mode 100644 index 0000000..3669b66 --- /dev/null +++ b/src/OID_analysis/Li22b.md @@ -0,0 +1,1227 @@ +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/28db442fab1a6012a8dac2c8d3557446b7576dd772aae22a52b348cb51467e88.jpg) + + +# Machine-learned control-oriented flow estimation for multi-actuator multi-sensor systems exemplified for the fluidic pinball + +Songqi Li1, Wenpeng Li1 and Bernd R. Noack1,† + +1School of Mechanical Engineering and Automation, Harbin Institute of Technology, 518055 Shenzhen, PR China + +(Received 14 May 2022; revised 1 October 2022; accepted 23 October 2022) + +We propose the first machine-learned control-oriented flow estimation for multiple-input, multiple-output plants. The starting point is constant actuation with open-loop actuation commands leading to a database with simultaneously recorded actuation commands, sensor signals and flow fields. A key enabler is an estimator input vector comprising sensor signals and actuation commands. The mapping from the sensor signals and actuation commands to the flow fields is realized in an analytically simple, data-centric and general nonlinear approach. The analytically simple estimator generalizes linear stochastic estimation for actuation commands. The data-centric approach yields flow fields from estimator inputs by interpolating from the database – similar to Loiseau, Noack & Brunton (J. Fluid Mech., vol. 844, 2018, pp. 459–490) for unforced flow. The interpolation is performed with k nearest neighbours (kNN). The general global nonlinear mapping from inputs to flow fields is obtained from a deep neural network (DNN) via an iterative training approach. The estimator comparison is performed for the fluidic pinball plant, which is a multiple-input, multiple-output wake control benchmark (Deng et al., J. Fluid Mech., vol. 884, 2020, A37) featuring rich dynamics under steady controls. We conclude that the machine learning methods clearly outperform the linear model. The performance of kNN and DNN estimators are comparable for periodic dynamics. Yet the DNN performs consistently better when the flow is chaotic. Moreover, a thorough comparison regarding the complexity, computational cost and prediction accuracy is presented to demonstrate the relative merits of each estimator. The proposed method can be generalized for closed-loop flow control plants. + +Key words: machine learning, big data + +## 1. Introduction + +Taming turbulence in the flow represents significant economic and environmental benefit in most industrial applications (Brunton & Noack 2015). Turbulence control plays a significant role in drag reduction (for example, see Choi, Moin & Kim 1994; Lee et al. 1997; Chamorro, Arndt & Sotiropoulos 2013). For the example of transport vehicles, aerodynamic drag accounts for approximately 15 % of the round-trip fuel consumption for a coal train (Stodolsky & Gaines 2003), and for cars overcoming aerodynamic drag, it takes up most of the power consumption at highway speeds (Sudin et al. 2014). A drag reduction of around 25 % in a three-dimensional bluff body reported by Pfeiffer & King (2012) indicates turbulence control as a remarkable energy saving strategy that is potentially applicable to all relative industries. + +To tackle the turbulence control problems, myriads of control strategies have been proposed (Joslin & Miller 2009), and these strategies can be classified principally into passive and active categories. For passive control, small modifications of the flow configuration are implemented to improve the surrounding flow, such as the installation of vortex generators to reduce drag on a car (Mukut & Abedin 2019), and the application of a chevrons nozzle to enhance the jet mixing (Zaman, Bridges & Huff 2011). Active control requires energy input to the flow domain from the actuators. Different types of active actuators, such as synthetic jets (Amitay et al. 2001), plasma actuators (Wang et al. 2013) and moving surfaces (Modi 1997), have been applied widely in the flow control experiments, with significant improvement of flow performance (Cattafesta & Sheplak 2011). For either control strategy, the control devices can be described in a parametrized manner, such as the shape parameters of the vortex generator or the duty cycles of the plasma actuators. These parametrized flow control devices will alter the dominant turbulent structures in the original flow, and generate distinct flow patterns according to the selection of the control parameters. + +In the typical flow control set-up, pointwise sensors, such as hotwire probes, pressure transducers and shear stress sensors, are placed sparsely in the flow or on the boundary. The deployment of these sensors makes it possible to recover the flow state from sparsely sampled sensor signals that comprise partial information of the flow state. The full state estimation from sparse sensors is of great importance in terms of flow control (Taylor & Glauser 2004). The accurate estimation of the full or partial flow state has the potential to notably improve the control outcome via a carefully designed controller, leading to remarkable drag reduction, mixing enhancement, noise attenuation, etc. (Brunton & Noack 2015). The machine learning architecture that couples a recurrent neural network and model predictive control in Bieker et al. (2020) is also proven to predict accurately and control the flow state from limited sensor data. For oscillatory dynamics, flow state estimation techniques based on reduced-order models (ROMs) have also been applied widely in the active flow control plants (see, for example, Tadmor et al. 2004; Barbagallo, Sipp & Schmid 2009). However, a sensor-based dynamic observer loses its accuracy with increasing state-space dimension even for a simple unforced oscillatory wake transient (Gerhard et al. 2003). Every extra degree of freedom may act as potential noise amplifier. A dynamic ROM, let alone estimation, is also a challenge for wall-bounded actuators with corresponding actuation commands as free input, as exemplified by Weller, Lombardi & Iollo (2009) for oscillatory dynamics. These challenges are even more pronounced for sensor-based estimation using ROMs for complex dynamics with multiple independent actuators. + +As the most commonly used technique, linear stochastic estimation (LSE; Adrian 1994), as well as its variants (Tinney et al. 2006; Lasagna, Orazi & Iuso 2013), establishes a 952 A36-2 + +linear model between sensor inputs and the flow state output (Clark, Naghib-Lahouti & Lavoie 2014). This method has been applied widely to either distil flow structures (Bonnet et al. 1994) or construct models for accurate flow estimation (Stalnov et al. 2007). The well-trained linear model can serve as a state estimation function in feedback flow control experiments (for example, see Samimy et al. 2007). Quadratic stochastic estimation (QSE) includes a nonlinear second-order term. These terms have been shown to be important for some wake estimation problems (Bourgeois, Martinuzzi & Noack 2013). Yet QSE calibration is computationally expensive (Murray & Ukeiley 2002). Challenges of QSE have already been reported in Tung & Adrian (1980). In contrast, neural network regression has become a mature methodology. + +The fast development of machine learning methods (Brunton, Noack & Koumoutsakos 2020) makes it possible to estimate the flow state via a spectrum of nonlinear approaches. A state estimation method based on the Autoencoder and the recurrent neural network is proposed by Kumar, Bahl & Chakraborty (2022) in which the flow field can be predicted accurately from few sensors. The comparison of neural network, LSE and gappy proper orthogonal decomposition (POD) is reported by Nair & Goza (2020) for the prediction of the laminar wake behind a fat plate from sparse sensor measurements. A series of convolutional neural network (CNN) based estimation architectures are proposed and evaluated by Güemes, Discetti & Ianiro (2019), Güemes et al. (2021) and Guastoni et al. (2021) to estimate the turbulent flow from wall measurements, and the results yield promising accuracy. The accurate estimation of the flow state from time-resolved sensor measurements and non-time-resolved velocity snapshots using long short-term memory (LSTM) is reported in Deng et al. (2019). Nevertheless, neither of these recent advancements in machine learning is designed naturally for multiple-input, multiple-output (MIMO) flow control. In the case of model-based feedback flow control, it is necessary to establish an estimation method that can accurately infer the flow state from sparse measurements under adjustable control commands. + +For the present study, we propose the first machine learning, sensor-based flow estimation that is capable of inferring the flow state from sparse measurements for MIMO plants. The k nearest neighbours (kNN) regression and deep neural network (DNN) serve as two nonlinear approaches, which represent a data-centric and a global nonlinear approach, respectively. In addition, LSE is employed as a linear reference point to highlight the significance of nonlinearity in the estimation problem. These methods are examined in the fluidic pinball plant, a cluster of three equal parallel cylinders centred on an equilateral triangle pointing upstream in a uniform flow (Bansal & Yarusevych 2017; Chen et al. 2020). This configuration is becoming an increasingly popular benchmark for MIMO flow control. The flow may be monitored using the forces on the cylinders or the velocity signals at selected locations. Actuation is performed with the rotation speed of each cylinder as control input. These actuations give rise to rich dynamics in the flow, and consequently it becomes challenging to obtain accurate flow estimation under a wide range of steady control commands. Meanwhile, a large spectrum of control algorithms have been applied to this plant (Peitz, Otto & Rowley 2020; Raibaudo et al. 2020; Blanchard et al. 2021; Cornejo Maceda et al. 2021; Ghraieb et al. 2021; Raibaudo & Martinuzzi 2021; Castellanos et al. 2022; Li et al. 2022). The fluidic pinball wake has been investigated in detail by Noack et al. (2016), Ishar et al. (2019), Deng et al. (2020, 2021a,b, 2022), Cortina-Fernández et al. (2021), Chen, Raiola & Discetti (2022) and Menier et al. (2022), among many others. + +This paper is organized as follows. The problem set-up of the control-oriented flow estimation problem and the estimation procedure are detailed in § 2.1, followed by the introduction of data compression (POD, § 2.2) kNN (§ 2.3), DNN (§ 2.4) and LSE (§ 2.5). Section 3 introduces the fluidic pinball plant as well as the numerical database that will be used in this study. The comparison of three estimation methods exemplified for the fluidic pinball plant is presented in $\ S 4 .$ . Sections 4.2–4.4 show the estimation results for three representative cases that correspond to the specific flow control strategies. The overall performance of each estimation method is concluded in § 4.5, followed by the conclusions and outlook in $\ S 5$ + +## 2. Nonlinear, control-oriented flow estimation + +In this section, we introduce control-oriented, sensor-based flow estimation that is capable of evaluating the flow state under various steady control commands. The set-up of the estimation problem, as well as the general estimation procedure, is described in § 2.1, and the data pre-processing technique is introduced briefly in § 2.2. To tackle the estimation problem, we propose a spectrum of data-driven estimators in this work. Two machine-learning-based approaches, i.e. k nearest neighbours (kNN) regression and deep neural network (DNN), will be introduced in §§ 2.3 and 2.4, respectively. In addition, the traditional linear stochastic estimation (LSE) method, which serves as a reference point in the present work, will be explained in § 2.5. + +## 2.1. Problem set-up and estimation procedure + +For stationary flow under a range of steady control commands, our objective is to estimate the instantaneous two-dimensional velocity field ${ \boldsymbol { u } } _ { b } ( { \boldsymbol { x } } )$ from the known information, which includes the instantaneous sensor signal s and the control command b. Here, the velocity vector is defined as $\boldsymbol { u } _ { b } = ( u , v )$ , and the spatial domain $\boldsymbol { x } = ( x , y )$ is bounded in $\mathbb { R } ^ { 2 }$ . The control command $\pmb { b } = [ b _ { 1 } , \ldots , b _ { M } ] ^ { \mathrm { T } }$ is composed of all parametrized actuation instructions from a total of M actuators in the flow. Each actuation instruction is bounded in R such that the control command $\pmb { b }$ is located in a finite high-dimensional space $\mathcal { D } \in \mathbb { R } ^ { M }$ For the fluidic pinball plant that will be examined in this study, b represents the rotation speeds of cylinders that are placed in the flow. For other relevant flow control applications, b may also represent duty cycles of the mini-jet/plasma actuators, shape parameters of the passive control devices, etc. A local sensor signal $\boldsymbol { s } = [ s _ { 1 } , \ldots , s _ { L } ] ^ { \hat { \mathrm { T } } }$ contains partial information about the flow field. The sensors are placed at sparse locations $\{ \boldsymbol { x } _ { s } ^ { ( i ) } \} _ { i = 1 } ^ { L }$ , and the measurement is equivalent to a masking function $\mathcal { G }$ that preserves the flow state at sensor locations. The challenge of this study is to establish a mapping function $\mathcal { F }$ from local sensor signal s and the actuation command b to the estimation of the corresponding flow state $\hat { u } _ { b } ( x )$ under control. + +To achieve this goal, we propose a data-driven procedure to estimate the flow state under different control laws. Figure 1 outlines the estimation procedure exemplified for the fluidic pinball, which is a benchmark problem that will be examined in this study. This plant contains multiple control commands $( b _ { 1 }$ to $b _ { 3 } )$ and multiple sensor measurements $( s _ { 1 }$ to s ); details will be introduced in $\ S 3$ . For most sensor-based flow state estimation methods, only sensor signals are utilized as the input. However, to include the influence of different control commands to the flow state, in this study we employ a combined input vector q that comprises the sensor signal s and the control command $^ { b , }$ such that + +$$ +\boldsymbol {q} = [ \boldsymbol {s}, \boldsymbol {b} ] ^ {\mathrm{T}} \in \mathbb {R} ^ {L + M}.\tag{2.1} +$$ + +The effectiveness of this algorithmically easy extension of the estimator input in the parameter direction has been proved in Hasegawa et al. (2020). In this pioneering work, a CNN-LSTM-based reduced-order model is established for flow at different Reynolds numbers. Here, we extend this approach and include high-dimensional actuation parameters to the input vector. For the purpose of establishing a data-driven mapping from the combined input q to the flow state $\mathbf { \delta } _ \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta } \mathbf { \delta \delta } \mathbf { \delta } \mathbf { \delta \delta } \mathbf { \delta \delta } \mathbf { \delta \delta } \mathbf { \delta \delta } \mathbf { \delta \delta } \mathbf { \delta \delta } \mathbf { \delta \delta } \mathbf { \delta \delta }$ , we first construct a database that contains massive input–output pairs under a set of $N _ { b }$ randomly generated control commands. These control commands are denoted as $\boldsymbol { B } = \{ b _ { j } \} _ { j = 1 } ^ { N _ { b } }$ . For numerical plants, the flow snapshots are calculated from the numerical solver, and the sensor signals s are obtained by masking the flow field according to the sensor locations. For experimental applications, the data can be acquired from synchronous measurements between particle image velocimetry and hotwire probes/pressure sensors (for example, see Tu et al. 2013). + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/05aac5ca4ce669817d37b910b20f7b214ddc488827fe6ba989c61baacafda1cc.jpg) + + + +Figure 1. A flow chart of control-oriented full-state estimation exemplified for the fluidic pinball plant and the DNN estimator + + +Based on the well-established database described above, data-driven estimation can be performed to optimize and generalize the mapping function. Nevertheless, given the high-dimensional nature of the flow state space, it is computationally expensive to estimate the velocity vector at every point inside the flow domain. Hence a reduced-order representation of the flow field is required prior to the application of any estimation algorithm. Different types of dimensionality reduction techniques have been proposed and are proven to be successful, including but not limited to deep Autoencoder (Fukami, Nakamura & Fukagata 2020), the POD (Lumley 1967) and wavelet transform (Bruce, Koger & Li 2002). In this work, a POD-based approach is employed to reduce the complexity of the flow snapshots. The application of POD does not involve any pre-training, which is typically computationally expensive, and the resulting POD eigenfunctions are human-interpretable. In this work, the database that includes all flow snapshots is pre-processed with a nearly lossless POD that compresses the high-dimensional data onto an energy-optimum, low-dimensional subspace (see § 2.2). Consequently, the estimation of instantaneous flow snapshots is equivalent to the estimation of the first N POD modal coefficients a, which take up the majority of fluctuating energy in the flow. + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/fd6c6c23f7fee8dff50487fdc506cf798d394362ef83a3c0f55d209f84d42cca.jpg) + + + +Figure 2. A graphical illustration of the three estimation methods. Scattered points represents true data. LSE (grey) fits the data in a linear manner. kNN (red) estimates from the neighbourhood observations (light blue). DNN (yellow) optimizes the input–output relationship by a globally nonlinear function. + + +The generation of the database containing flow snapshots under various control laws, and the application of the dimensionality reduction technique, enable us to estimate the flow state via a spectrum of estimators that are capable of learning the mapping function $\mathcal { F } : q a$ from a total of $N _ { s }$ input–output observation pairs $\mathcal { M } : \{ ( \boldsymbol { q } ^ { ( j ) } , \boldsymbol { \pmb { a } } ^ { ( j ) } ) \} _ { j = 1 } ^ { N _ { s } }$ recorded under different control commands in the set $B .$ . In this work, three representative estimators are proposed, and a graphical illustration of these data-driven methods can be found in figure 2. The kNN regression acts as a locally nonlinear approach; this method learns the mapping from its neighbourhood observations via a non-parametric, distance-based interpolating process. The DNN establishes a globally nonlinear model and optimizes the internal parameters of the model through an iterative optimization routine. For LSE, a linear relationship between inputs and outputs is first assumed, then a least-squares fit is performed to minimize the estimation error. These estimation methods, as well as the POD-based data compression technique, will be introduced in the following subsections. + +## 2.2. Data pre-processing: the proper orthogonal decomposition + +In this study, the snapshot POD (Sirovich 1987) is employed as a data pre-processing technique, which reduces the computational cost of the estimation by compressing the high-dimensional flow snapshots onto a low-dimensional orthonormal subspace where energy is optimized. As we do not include the time coordinate for the control-oriented flow estimation in this study, Koopman-style decomposition techniques (Chen, Tu & Rowley 2012) are not available for the data pre-processing. Given a set of flow snapshots under various control commands in $B ,$ , a velocity decomposition is first performed that splits the velocity vectors $\scriptstyle { \pmb u } _ { b }$ into the mean and fluctuating components: + +$$ +\boldsymbol {u} _ {\boldsymbol {b}} (\boldsymbol {x}, t) = \boldsymbol {u} _ {\mathcal {B}} (\boldsymbol {x}) + \boldsymbol {u} _ {\boldsymbol {b}} ^ {\prime} (\boldsymbol {x}, t).\tag{2.2} +$$ + +Here, $\pmb { u } _ { B }$ represents the mean velocity component, and $\pmb { u } _ { b } ^ { \prime }$ is the fluctuating counterpart. In this work, the mean velocity u is defined as the ensemble average over time t and all control laws in the set : + +$$ +\boldsymbol {u} _ {\mathcal {B}} (\boldsymbol {x}) = \langle \boldsymbol {u} _ {\boldsymbol {b}} (\boldsymbol {x}, t) \rangle_ {\boldsymbol {b}, t},\tag{2.3} +$$ + +where $\langle \cdot \rangle _ { b , t }$ represents the ensemble average over both control commands and time instances. For the fluctuating velocity $\pmb { u } _ { b } ^ { \prime } .$ , we apply the snapshot POD and expand the velocity field based on a series of orthonormal POD eigenfunctions. As the first N POD modes usually capture most of the energy and large-scaled coherent structures in the flow, an expansion of the fluctuating velocity can be formulated as + +$$ +\boldsymbol {u} _ {\boldsymbol {b}} ^ {\prime} (\boldsymbol {x}, t) = \sum_ {k = 1} ^ {N} a _ {k} (\boldsymbol {b}, t) \boldsymbol {u} _ {k} (\boldsymbol {x}).\tag{2.4} +$$ + +Here, $\pmb { u } _ { k }$ represents the orthonormal eigenfunction of the kth POD mode, and $a _ { k }$ the corresponding modal coefficient which contains the energy trace. Since the eigenfunctions $\pmb { u } _ { k }$ are invariant with time and control command, the velocity expansion in (2.4) simplifies the full-state estimation problem to the estimation of the POD modal coefficients ${ \pmb a } =$ $[ a _ { 1 } , \ldots , a _ { N } ] ^ { \mathrm { T } }$ . As a result, a significant reduction of the computational cost can be achieved. After the estimates of the POD coefficients are obtained, the flow field can be reconstructed according to (2.2) and (2.4). + +## 2.3. k nearest neighbours regression + +To establish a mapping function $\mathcal { F } : q a$ for the purpose of flow estimation, we first introduce the kNN (Stone 1977) regression algorithm. This method is a locally nonlinear estimation approach, and a schematic diagram of kNN is presented in figure 3. kNN adopts a non-parametric approach where the mapping function $\mathcal { F }$ is approximated locally by averaging a subset of K observations in which the input data reside in the same neighbourhood of the observations. In this study, a weighted average over the first K nearest neighbours is carried out based on the distance between the estimation input and the neighbourhood observations, such that the output can be approximated by the equation + +$$ +\hat {\boldsymbol {a}} (\boldsymbol {q}) = \frac {\sum_ {i = 1} ^ {K} \boldsymbol {a} (\boldsymbol {q} ^ {(i)}) 1 / d (\boldsymbol {q} , \boldsymbol {q} ^ {(i)})}{\sum_ {i = 1} ^ {K} 1 / d (\boldsymbol {q} , \boldsymbol {q} ^ {(i)})}.\tag{2.5} +$$ + +In this equation, $d ( \pmb { \alpha } _ { 1 } , \pmb { \alpha } _ { 2 } )$ represents the distance between vectors ${ \pmb { \alpha } } _ { 1 }$ and $\pmb { \alpha } _ { 2 }$ , and the Euclidean distance $\| { \pmb { \alpha } } _ { 2 } - { \pmb { \alpha } } _ { 1 } \| _ { 2 }$ is adopted throughout this study. Here, $\pmb { a } ( \pmb q ^ { ( i ) } )$ denotes the output in the observation set that corresponds to the combined input $\pmb q ^ { ( i ) }$ . The superscript (i) represents the ith nearest neighbour in the observation set based on the measurement of distance in the input space, and the parameter K stands for the number of neighbourhood observations that are utilized during the averaging process. In general, the value of K in (2.5) needs to be determined empirically. A small K means that the result can be influenced greatly by the outlying observation and random noise, while a large value is usually computationally expensive. Therefore, a convergence study is carried out to determine the optimal value of K used in this study. Figure 4 shows the normalized mean-squared estimation error $( \mathrm { i } . \mathrm { e } . \ E ^ { 2 }$ in (3.5)) of kNN under different K values for the fluidic pinball plant, from which $K = 1 0$ is selected in an effort to balance the accuracy and the computational efficiency. + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/41adc91e5ea0a41d50aa549caadc0e5db527a9bef6909e942b00571f4326653b.jpg) + + + +Figure 3. A schematic of kNN for the control-oriented flow estimation. + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/bd2fbe04684ba35c25aacde48bb237c2328a15b1894351367a618c41563a214a.jpg) + + + +Figure 4. Mean-squared error (MSE) of kNN under different neighbourhood numbers K in (2.5). + + +## 2.4. Deep neural network + +As the second approach, we employ DNN to approximate the mapping function $\mathcal { F }$ in a globally nonlinear manner. In general, DNN is composed of several layers of artificial neurons that are connected to one another. For each layer, a linear transformation of the input data $y _ { i n }$ is first performed with tunable weights W and biases c, then a nonlinear activation function $\sigma$ is exerted, such that + +$$ +\pmb {y} _ {o u t} = \sigma (\pmb {W} ^ {\mathrm{T}} \pmb {y} _ {i n} + \pmb {c}).\tag{2.6} +$$ + +Here, $y _ { i n } \in \mathbb { R } ^ { n _ { i n } } , y _ { o u t } \in \mathbb { R } ^ { n _ { o u t } }$ $\pmb { W } \in \mathbb { R } ^ { n _ { i n } \times n _ { o u t } }$ and $c \in \mathbb { R } ^ { n _ { o u t } }$ . By stacking multiple layers of artificial neurons sequentially and assigning the output from one layer as the input to the next layer, DNN has the potential to accurately approximate complex nonlinear functions by learning weights and biases from data (Hornik, Stinchcombe & White 1989). + +A schematic of the DNN architecture used for control-oriented flow estimation can be found in figure 5. Here, the sensor signal components $s _ { 1 }$ to $s _ { L }$ , as well as the control command parameters $b _ { 1 }$ to $b _ { M }$ , are concatenated and form the input of the neural network. + +Control-oriented flow estimation for the fluidic pinball + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/5410a6b5e9f6cb19d43e7c5ee47b741eca7f82c9f4ac3464e955dc9da8d4f73a.jpg) + + + +Figure 5. A schematic of a DNN for control-oriented flow estimation + + +
DNN architectureParameters
Input layer size12 (s \in \mathbb{R}^{9}, b \in \mathbb{R}^{3})
Output layer size78 (a \in \mathbb{R}^{78})
Hidden layer sizes256, 256, 256
Activation functionReLU (Agarap 2018)
InitializationXavier (Glorot & Bengio 2010)
Input–output scalingMin–max → [0,1]
Batch size64
OptimizerAdam (Kingma & Ba 2014)
LossMSE (L_{\varepsilon})
Number of epochs500
Number of repetitions20
+ + +Table 1. The set-up of the DNN applied for the fluidic pinball plant. + + +The output of the neural network contains the truncated POD modal coefficients $a _ { 1 }$ to $a _ { N }$ Both the combined input vector q and output vector a are re-scaled into the range [0, 1] to facilitate convergence. Note that in kNN and LSE, the input vector is non-dimensionalized to an amplitude of O(1) by the freestream velocity $U _ { \infty }$ , which is in accord with the recommendation in Burkov (2019). + +A brief summary of the DNN architecture applied in this study can be found in table 1. The architecture of the neural network is determined empirically by balancing the estimation accuracy and the computational cost. Based on the dimension of the combined input vector and the POD modal truncation (see § 4.1), the sizes of the input and the output layers are 12 and 78, respectively. Three 256-node hidden layers are fully connected in between, for each neuron for which the rectified linear activation function (ReLU; Agarap 2018) is specified as the activation function. + +To minimize the loss function that indicates the performance of the neural network, all tunable weights and biases are optimized with gradient-based back-propagation via an iterative training approach (LeCun, Bengio & Hinton 2015). In this study, the Adam optimization method (Kingma & Ba 2014) is adopted, and the corresponding loss function is defined as $L _ { \varepsilon } = \langle \| \pmb { a } - \mathbf { \hat { a } } \| _ { 2 } ^ { 2 } \rangle$ , which represents the mean squared error between the desired output a and the actual output aˆ over the training samples. To accelerate the training phase and avoid the convergence to local minimum, the iterative back-propagation is achieved based on the evaluation of mini-batches that are partitioned randomly from the training data. In the present work, the batch size is set to 64, and a total number of 500 epochs were carried out to train the model. Other key settings related to the fluidic pinball dataset applied in this work, including the dataset partition and the iterative training process, will be detailed in § 3.4. + +Before the iterative training, all weights are initialized randomly following the suggestion in Glorot & Bengio (2010). In this method, the randomly generated initial weights yield Gaussian distributions, and the initial biases are set to zero. To examine the influence of randomness from the network initialization to the estimation outcome, we trained the network 20 times, and for each time the initial weights are randomly generated. We calculate the averaged outputs and their variances based on the test set, and present these results in $\ S 4$ + +## 2.5. Linear stochastic estimation + +Besides the nonlinear, machine-learning-based methods, we apply LSE (Adrian 1994) as a reference point in this study. LSE represents the most general linear fit between fluctuating sensor signals and POD modal coefficients. The solution of LSE is equivalent to the least-squared estimation error for the estimation of POD modal coefficients. As presented in figure 6, this method analytically optimizes a linear input–output model, such that + +$$ +a _ {i} (\boldsymbol {b}, t) = \sum_ {j = 1} ^ {N} \boldsymbol {\tau} _ {i j} q _ {j} (t).\tag{2.7} +$$ + +Multiplying by $q _ { k }$ on both sides of (2.7) and taking the ensemble average over b and t, we get + +$$ +\sum_ {j = 1} ^ {N} \boldsymbol {\mathsf {T}} _ {i j} \langle q _ {j} q _ {k} \rangle_ {\boldsymbol {b}, t} = \langle a _ {i} q _ {k} \rangle_ {\boldsymbol {b}, t}.\tag{2.8} +$$ + +Here, $\langle q _ { j } q _ { k } \rangle _ { b , t }$ denotes the cross-correlation between inputs, and $\langle a _ { i } q _ { k } \rangle _ { b , t }$ represents the autocorrelation between inputs and outputs. Both matrices can be computed directly from data, and a least-squares solution of $\tau _ { i j }$ can be obtained by solving (2.8). + +So far, we have described the control-oriented, sensor-based flow estimation problem, as well as a spectrum of machine learning flow estimation methods that are capable to tackle this problem. In the next section, we will present the numerical plant, i.e. the fluidic pinball, that will be utilized in this study to evaluate the performance of these estimation methods. + +## 3. Numerical plant: the fluidic pinball + +In this section, we introduce the fluidic pinball as a benchmark plant to evaluate control-oriented flow estimation methods described in § 2. An overview of the fluidic pinball is provided in § 3.1, followed by the description of the flow configuration and the numerical solver in § 3.2. The establishment of the fluidic pinball database that will be used in this study is detailed in § 3.3, including control commands generation and data sampling, as well as sensor placement. The partition of the database for the purpose of establishing data-driven mappings, as well as the criteria to evaluate the estimation performance, will be concluded in § 3.4. + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/62f05e70163fb605516383b22db58146c1a23a5747bd8391d5f264c530a479f2.jpg) + + + +Figure 6. A schematic of the LSE algorithm for the control-oriented flow estimation. The yellow column and light yellow column represent the sensor signal s and control command b, respectively. The orange column represents the estimation of the POD modal coefficients a. Dots in the transfer matrix correspond to the weights of T , which is visualized under a blue (negative)–white (0)–red (positive) colour scheme. + + +## 3.1. An overview of the fluidic pinball plant + +The fluidic pinball plant is a classical control problem that contains rich dynamical behaviours thanks to different flow control inputs (Ishar et al. 2019). This plant is composed of a two-dimensional, uniform flow passing a set of three cylinders of the same diameter D. The centres of the three cylinders form an equilateral triangle pointing in the upstream direction, and the side length of the triangle is 1.5D. The unforced flow exhibits six different Navier–Stokes solutions, including two stable statistically asymmetric periodic vortex sheddings (Deng et al. 2020, 2021a). The independent rotation of three cylinders allows the control of the wake formed downstream, and is capable of replicating most known control mechanisms, namely, phasor control, stagnation point control, boat tailing and base bleeding, as well as high- and low-frequency forcing (Ishar et al. 2019; Cornejo Maceda et al. 2021). In this study, only steady, open-loop control commands are considered. Apart from the uncontrolled case with periodic vortex shedding, steady rotations of cylinders enables the realization of stagnation point control, boat tailing and base bleeding. The schematics of these control mechanisms can be found in figure 7. With the stagnation point control, a unified rotation is exerted on the three cylinders, from which the incoming flow is deflected following the cylinder rotation direction thus attenuated periodic vortex shedding (Seifert 2012). Both boat tailing and base bleeding mechanisms starts from the counter-rotation of the two rearward cylinders. With boat tailing, the top cylinder rotates clockwise and the bottom rotates counter-clockwise. This will guide the boundary layer flowing towards the centre region downstream of the cylinders, which delays the flow separation and leads to significant drag reduction (Geropp & Odenthal 2000; Evrard et al. 2016). When the top cylinder rotates counter-clockwise and the bottom rotates clockwise, the base bleeding mechanism takes place, which generates a fluid jet on the centreline. The jet actuation will limit the interaction between upper and lower shear layers, hence impairing the development of large-scale vortices downstream. The ability of the base bleeding mechanism to reduce bluff-body aerodynamic drag has been reported in Wood (1964), Bearman (1967) and Howell, Sheppard & Blakemore (2003), among many others. With the deployment of sparse sensors in the flow, the fluidic pinball forms an MIMO system. Here, we focus + +S. Li, W. Li and B.R. Noack + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/3bf2c10a8f2b27c12830f2482e69edcd961d528a55ed1ccb3b6555a4c1a3fb1f.jpg) + + + +Figure 7. A graphical illustration of three flow control mechanisms in the fluidic pinball plant. Figures from Lin (2021). (a) Stagnation point control. (b) Boat tailing. (c) Base bleeding. + + +on the application of sensor signal, along with the control command, to estimate the instantaneous flow field under steady control. + +## 3.2. Flow configuration and numerical solver + +The flow is depicted in a two-dimensional Cartesian coordinate system, where the origin is located on the midpoint of the two rear cylinders. The x axis represents the streamwise direction, and the y axis points perpendicular to the freestream direction. Both axes are scaled by the diameter of the cylinders. The velocity vector is scaled by the freestream velocity $U _ { \infty }$ , and is denoted by $\boldsymbol { u } = ( u , v )$ , where u represents the streamwise velocity, and v the transverse velocity. In this study, we consider an incompressible Newtonian fluid with constant density $\rho$ and kinematic viscosity ν. The Reynolds number based on the cylinder diameter D is defined as $R e _ { D } = U _ { \infty } D / \nu$ . Throughout this study, the Reynolds number is set to 100, which corresponds to the asymmetric periodic vortex shedding according to Deng et al. (2020). The computational domain Ω is bounded by a rectangular box $[ - 6 , 2 0 ] \times [ - 6 , 6 ]$ externally and the three cylinders internally: + +$$ +\begin{array}{c} \Omega = \{[ x, y ] ^ {\mathrm{T}} \in \mathcal {R} ^ {2}: [ x, y ] ^ {\mathrm{T}} \in [ - 6, 2 0 ] \times [ - 6, 6 ] \cap (x - x _ {i}) ^ {2} \\ + (y - y _ {i}) ^ {2} \geqslant 1 / 4, i = 1, 2, 3 \}. \end{array}\tag{3.1} +$$ + +Here, $x _ { i }$ and $y _ { i }$ represent the centres of the three cylinders positioned in the flow, where + +$$ +\left. \begin{array}{l l} x _ {1} = - 3 / 2 \cos (3 0 ^ {\circ}), & y _ {1} = 0, \\ x _ {2} = 0, & y _ {2} = - 3 / 4, \\ x _ {3} = 0, & y _ {3} = 3 / 4. \end{array} \right\}\tag{3.2} +$$ + +The computational domain Ω is discretized by the unstructured mesh shown in figure 8. This mesh contains 4225 triangles and 8633 vertices. The grid independence of the direct Navier–Stokes solutions has been established by Deng et al. (2020). + +The boundary conditions for the inflow, upper and lower boundaries are specified as the freestream velocity $U _ { \infty }$ and a stress-free condition is assumed at the outflow boundary. To model the steady rotation of the cylinders, a no-slip condition is enforced on the cylinder boundaries. The flow adopts the circumferential velocities on the boundary of the front, bottom and top cylinders, which is specified by $b _ { 1 } = U _ { F } , b _ { 2 } = U _ { B }$ and $b _ { 3 } = U _ { T }$ . Here, $b _ { 1 }$ to $b _ { 3 }$ are scaled with $U _ { \infty }$ . For each cylinder, the rotation speed on the boundary is within the range [−2, 2]. A positive value corresponds to counter-clockwise rotation of the cylinders, and vice versa. The control command can then be written as $\pmb { b } = [ b _ { 1 } , b _ { 2 } , b _ { 3 } ] ^ { \mathrm { T } } \in$ $[ - 2 , 2 ] ^ { 3 }$ . The initial condition for the numerical simulations is the symmetric steady solution calculated from the steady Navier–Stokes equations. We use an in-house implicit finite-element method solver UNS3 (Noack & Morzynski´ 2017) that employs an implicit finite element method to perform numerical integration of Navier–Stokes equations with third-order accuracy in space and time. In this study, only the post-transient data are collected for the purpose of constructing the fluidic pinball database that will be used to model the input–output relationship between the sparse sensors and the flow state. We non-dimensionalize the time with $U _ { \infty }$ and $D .$ . For every control command, 100 snapshots are recorded with a time interval $\Delta t = 1$ . The numerical simulation under a single control command takes up around 1 core hour, and the data storage for 100 snapshots is approximately 78 MB. For the unforced flow, the vortex shedding period is approximately 8.5 times the non-dimensionalized time unit. We choose $\Delta t = 1$ in an attempt to balance the computational cost and the overall sampling range in time. The generation of control commands, as well as the placement of virtual sensors, will be detailed in the next subsection. + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/b9fba6710a06bc93eb4fffc902094d6d19976c91ac6d64f4574d8355c9232c5f.jpg) + + + +Figure 8. Computational grid for the fluidic pinball simulation. + + +## 3.3. Control command generation and sensor placement + +To establish control-oriented flow estimators, a set of 1000 different control commands $B = \{ b _ { j } \} _ { j = 1 } ^ { 1 0 0 0 }$ are generated randomly inside the control parameter space $[ - 2 , 2 ] ^ { 3 }$ . As mentioned in § 3.2, the control parameter $\pmb { b }$ represents the circumferential rotation speed of three cylinders in the flow. Here, we employ the Latin hypercube sampling (McKay, Beckman & Conover 1979) to obtain a set of randomly distributed control commands . As presented in figure 9, this sampling method ensures a nearly uniform distribution of samples inside the multi-dimensional control parameter space. For each control command, we categorize the flow state into periodic and chaotic types after the flow snapshots are obtained from the numerical solver. The classification criteria are based on the relationship between two variables, $\gamma _ { 1 }$ and $\gamma _ { 2 }$ , obtained from the sampled snapshots. Here, $\gamma _ { 1 } = C _ { L } ( t )$ and $\gamma _ { 2 } = ( C _ { L } ( t + \Delta t ) - C _ { L } ( t ) ) / \Delta t .$ , and $C _ { L }$ represents the lift coefficient. The lift coefficient is computed by integrating pressure over the surfaces of three cylinders. From these plots, different characteristics between periodic and chaotic flows can be distinguished clearly. Representative periodic and chaotic phase pattern approximations are displayed in figure 9. For periodic flows, the discrete points in the plots will form circular or periodic trajectories. In contrast, the patterns in chaotic flows are dispersed and disordered. The classification of the flow state will enable us to evaluate the performance of the flow estimators introduced in § 2 under different types of the flow states. + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/5d891088040fb4f41d534d06e023bda4b9be6cc863e90b30f0268354d9d65fec.jpg) + + + +Figure 9. Randomly sampled control commands in the control space $[ - 2 , 2 ] ^ { 3 }$ and their projections on the three orthogonal coordinate planes. Periodic and chaotic cases are rendered by red and blue dots, respectively. Representative patterns of $\gamma _ { 1 }$ versus $\gamma _ { 2 }$ in each category are also presented in this figure. See the text for the definitions of $\gamma _ { 1 } , \gamma _ { 2 }$ + + +
SensorsxyVelocity
s_1, s_2, s_35, 6.5, 81.25Streamwise
s_4, s_5, s_65, 6.5, 80Spanwise
s_7, s_8, s_95, 6.5, 8-1.25Streamwise
+ + +Table 2. Virtual sensor locations and the corresponding velocity components. + + +To monitor the flow state, nine virtual probes are placed downstream to measure the discrete velocity signal, in either the streamwise or spanwise component. The velocity probes are deployed as a $3 \times 3$ rectangular grid symmetric about the centreline, where the upper and lower sensors measure the streamwise velocity, and the middle ones on the centreline measure the spanwise velocity. The streamwise locations of the sensors are $x = 5 , 6 . 5 , 8$ , and the spanwise locations are $y = - 1 . 5 , 0 , 1 . 5$ . This sensor placement has been validated by Cornejo Maceda et al. (2021), in a sense that such arrangement is capable of detecting large-scaled vortex shedding while encompassing phase information between sensors in its feedback flow control experiment. In other words, this arrangement can help to infer the flow state in the dynamically controlled flow with a wide range of control commands. Hence in this work, we continue to use this promising sensor placement to obtain flow state estimation. A summary of the sensor placement can be found in table 2, and a comprehensive visualization regarding the flow state, control parameters and downstream sensing is presented in figure 10. + +## 3.4. Data partition and estimation performance evaluation + +According to the steady control command and virtual probe placement described above, the fluidic pinball database is established aiming for sensor-based, control-oriented flow estimation. To preserve the generality of the data-driven estimation and prevent over-fitting, the collected input–output data pairs are partitioned into a training set, a validation set, and a test set based on a random split of the control commands . The partition of the control commands follows an 80 %–10 %–10 % ratio, and each set is composed of all time instances generated from the corresponding control commands. The training and validation sets compose the observation data , and will be utilized for the neighbourhood searching in kNN and the calculation of $T _ { i j }$ in LSE. To prevent over-fitting the training data in DNN, the iterative training and gradient-based back-propagation are performed only on the mini-batched training set. After every epoch, we evaluate the model performance on the validation set. The network parameters corresponding to the minimum validation loss over the 500 epochs are outputted after training. The number of epochs is determined empirically by observing the fact that the training loss will hardly be minimized after 500 epochs. For all estimation methods, the test set is not accessible during the training stage. Therefore, with this separate set, we can evaluate the generalized performance of the proposed methods. All key parameters regarding the fluidic pinball database have been concluded and presented in table 3. + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/9811c7b655dff05537e093908ea1311e6b879d2703dfcc4dbe13ce8dbee72ac8.jpg) + + + +Figure 10. Visualization of sensor placement in the flow domain. The background is rendered by an instantaneous vorticity field. The corresponding control command b is visualized by the colours on the three cylinders, under a blue (negative)–white (0)–red (positive) colour scheme. + + +
ParametersValue
Control parameters\boldsymbol{b} \in [-2, 2]^{3}
Number of control commands1000
Number of snapshots per case100
Sampling time interval1
Training set80 %
Validation set10 %
Test set10 %
+ + +Table 3. A conclusion of the fluidic pinball database. + + +To evaluate the performance of each estimation method from various perspectives, different types of errors are defined and calculated based on the data from the test set. In this work, different types of errors will be discussed; the definitions are presented in the following. To evaluate the estimation performance under each control command, the normalized estimation error of the POD modal coefficients is defined as + +$$ +\varepsilon_ {a} (\boldsymbol {b}) = \sqrt {\frac {\langle \| \boldsymbol {a} - \hat {\boldsymbol {a}} \| _ {2} ^ {2} \rangle_ {t}}{\langle \| \boldsymbol {a} \| _ {2} ^ {2} \rangle_ {t}}}.\tag{3.3} +$$ + +Similarly, the normalized velocity estimation error $\varepsilon _ { u } ( x )$ evaluates the spatial distribution of the velocity estimation error that accounts for all time instances and control commands, which is normalized by the overall fluctuating energy, such that + +$$ +\varepsilon_ {u} (x) = \sqrt {\frac {\langle \| u _ {b} ^ {\prime} (x) - \hat {u} _ {b} ^ {\prime} (x) \| _ {2} ^ {2} \rangle_ {b , t}}{\langle \| u _ {b} ^ {\prime} (x) \| _ {2} ^ {2} \rangle_ {b , t}}}.\tag{3.4} +$$ + +Furthermore, we define the normalized overall estimation error $E ,$ which is a scalar representing the overall accuracy of each estimation method. The value of E is determined as the cumulative estimation error over the spatial domain, all control commands, and all temporal instances in the test set normalized by energy, such that + +$$ +E = \sqrt {\frac {\langle \int_ {\Omega} \| \boldsymbol {u} (\boldsymbol {x}) - \hat {\boldsymbol {u}} (\boldsymbol {x}) \| _ {2} ^ {2} \mathrm{d} \boldsymbol {x} \rangle_ {\boldsymbol {b} , t}}{\langle \int_ {\Omega} \| \boldsymbol {u} (\boldsymbol {x}) \| _ {2} ^ {2} \mathrm{d} \boldsymbol {x} \rangle_ {\boldsymbol {b} , t}}}.\tag{3.5} +$$ + +## 4. Results and discussion + +In this section, we apply the three estimation methods introduced in § 2 to the fluidic pinball plant. First, we present the results from the snapshot POD in § 4.1, which includes the energy distribution and the physical interpretation of the leading POD modes. Then the performances of the estimation methods are compared under three representative flow control commands that are selected from the test cases, and the results are presented in §§ 4.2, 4.3 and 4.4, respectively. Here, each control command represents a specific flow control mechanism introduced in § 3.1, and the comparison includes the estimation of reduced-order POD modal coefficients as well as the full-state flow field. Furthermore, the overall performance of each estimation method will be evaluated and discussed in § 4.5, and this section is closed by a concluding diagram (table 4) that contains a thorough assessment of each estimation method from various perspectives. Throughout this section, we adopt the non-dimensionalized form of the data and spatial dimensions, as introduced in § 3.2. + +## 4.1. The snapshot POD + +To perform sensor-based flow estimation, a necessary step is to find a reduced-order representation of the high-dimensional flow snapshots. In this work, we decompose the velocity into mean and fluctuating components according to (2.2), then apply the snapshot POD to describe the velocity field using the linear combination of the most energetic POD modes. Figures 11(a,b) present the ensemble-averaged mean streamwise velocity field and the intensity of the fluctuating velocity component $\sqrt { \langle u ^ { 2 } + v ^ { 2 } \rangle _ { b , t } }$ , respectively. For comparison, the corresponding profiles of the uncontrolled case $\pmb { b } = [ 0 , 0 , 0 ] ^ { \mathrm { T } }$ are also displayed in figures $1 1 ( c , d )$ . Unlike the unforced mean profiles, which are biased to the negative y direction due to the pitchfork bifurcation described in Deng et al. (2020), the profiles in figure 11 are seen to be symmetric about the centreline $y = 0$ thanks to the effect of control. In addition, one can clearly capture a reduced length of the separation region behind the cylinders, as well as the expansion of the most energetic region (in the sense of fluctuating velocity), when the flow is under random control. + +Following the velocity decomposition, we employ the snapshot POD to set up a reduced-order representation of the fluctuating velocity $\pmb { u } _ { b } ^ { \prime }$ . Figure 12 presents the energy distribution as well as the cumulative sum of the first 100 POD modes. The leading POD modes are seen to possess most of the fluctuating energy, in which the first two and the first ten modes take up 44.9 % and 78.9 % of the overall energy, respectively. A fast decay of the energy in lower-order POD modes is also observed. In an attempt to reduce the computational cost while preserving the most energetic flow structures, the modal truncation criterion is defined as 99 % of the total energy, which corresponds to the first 78 POD modes in this database. These modes will serve as the expected outputs to investigate the performance of the estimation methods. + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/262d5d7c400edbe0205ce459ccada707427f0ce44a64ac2f66f3c34424f122d1.jpg) + + + +Table 4. A comprehensive comparison of all estimation methods from different horizons. + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/1b67d96a6d275edd717f4166aef4848ad8141a6ee9a7f0998c7cff9dddac48a5.jpg) + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/699cb6feb0c22fc5f8cafc6ac382b47991e4c145e323c8c76153faa753438329.jpg) + + + +(c) + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/ac7dcfac48fe34c747781b9c93f9fabebec86f474d3f76989bfe6c2fc28c0b90.jpg) + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/0b7ff7a8372f07b401b50b1ac30510a3dbb3a93218425846c51a9e4fbd1ff92b.jpg) + + + +Figure 11. (a) Ensemble-averaged streamwise velocity field over 1000 different control commands, and (b) intensity of the fluctuating velocity. (c) Uncontrolled mean streamwise velocity field with pitchfork bifurcation (Deng et al. 2020), and (d) the corresponding fluctuating velocity intensity. + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/630d7247c4eadf96c1be1dcf10fa4070334c7e4ff1cc51177070f7fe4a987f54.jpg) + + + +Figure 12. Energy distribution of the leading POD modes and the cumulative sum. + + +Figure 13 presents the modal shapes of the first 9 dominant POD modes. Each contour represents the curl of the corresponding POD eigenfunction $( \nabla \times \pmb { u } _ { k } )$ . The combination of POD modes 1 and 2 can effectively depict the spatial structures of the von Kármán vortex street appearing downstream of the three cylinders. Modes 4 and 5 also represent the vortex shedding structures in the flow, and modes 8 and 9 describe the second harmonics of the dominant coherent structures. Although these structures can be recognized clearly from visualization, the shapes of these modes are no longer strictly symmetric/antisymmetric about the centreline thanks to the influence of cylinder rotations. To advance the physical understanding of POD modes 3, 4 and 7, we calculate the root-mean-square (r.m.s.) of these POD modal coefficients over time $( \sqrt { \langle a _ { i } ^ { 2 } ( b , t ) \rangle }$ for $i = 3 , 4 , 7 )$ for all $\pmb { b } \in \mathcal Ḋ B Ḍ$ . For each mode, we pick the first 30 control laws possessing the highest r.m.s. values, and visualize them in figure 14. In other words, these POD modes become more pronounced under the actuation commands displayed in the figure. Mode 3 plays the role of the shift mode between steady and time-averaged periodic solutions (Noack et al. 2003). Furthermore, as the control commands in figure 14 mostly locate around the boundary lines $b _ { 2 } = - 2 , b _ { 3 } = 2$ and $b _ { 2 } = 2 , b _ { 3 } = - 2$ , we find that this shift mode also represents the effect when the two rear cylinders rotate in opposite directions. Mode 4 is more energetic when the control commands approach the boundary points $[ - 2 , - 2 , - 2 ]$ and [2, 2, 2], hence this mode is related to the stagnation point control in which all cylinders rotate in a uniform manner. This causal relationship can be confirmed further by its modal shape, where a symmetrical pattern emerges from the separation points of the top and bottom cylinders. Finally, the control commands for mode 7 in figure 14 aggregate near [2, −2, −2] and [−2, 2, 2]. From this characteristic, we can infer that this mode is highly related to the control when the two rear cylinders rotate in the same direction, and the front cylinder rotates oppositely. + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/da272b529d35e59bb80307e1ee44bf97007bbb1ff615845e8865949dae88aed1.jpg) + + + +(b) + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/460e6235ffaf5a5f58c3d9e676ab197f9e5262044775cd6527300384b750af99.jpg) + + + +(d ) + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/d1a6ba4624f6b7a79b8cdf00fbb9ba7cbe93a362133f8779dbeddcc95a751b5c.jpg) + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/19e32ed3de6dca1ee8b5300c21f54a7f16e9b32911a2f47c3cb03c2dd4a19274.jpg) + + + +(e) + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/2fd06a3b511310526c1020771ae544d8638b09a239e4ded27a0f19e4b143edf5.jpg) + + + +( f ) + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/f10a35fe3615b0789e2c9a178b65f21cc656a8bfc755639a49751a2480856973.jpg) + + + +( ) + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/d1feb4abb7c8b2a0f023ecb06b822d0ae6de6b43572ff91fe7c9daf040154fe2.jpg) + + + +( ) + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/d95a75232219fdead647e3a88c6bb4ad08ee3555ed1cd3fc8dcaa721cfb445ee.jpg) + + + +( ) + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/f734c179decf0fcfccc30ebcf4175bd6faf8bd6da68fca0a90f66f21231d7777.jpg) + + + +Figure 13. Modal shapes of the first 9 POD modes visualized in vorticity $( \nabla \times \pmb { u } _ { k } )$ + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/a431530424df7418dacf33c94093a11fdefa80de246ad50a333dcd0b6cf1bc24.jpg) + + + +Figure 14. Distribution of the first 30 control commands that possess the highest overall amplitudes of th POD modal coefficients for modes 3, 4 and 7. + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/c58642c76c0bf001f5c8b134a363f5facc995d05cda03632312ac0e7a757095a.jpg) + + + +(b) + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/49d56fdde995b13af5be4ba21f25dda64fb4a780497f76da842b882888de6baf.jpg) + + + +(c) + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/919278df2578f8198de71e392231c7b7d26e4a5fa1b3c24a6c2a92435c32017b.jpg) + + + +Figure 15. Phase relationship (a versus a ) obtained from the three estimation methods and the $L _ { 2 }$ error associated with the first two modes in the boat tailing case: (a) LSE, (b) kNN, (c) DNN. Black dots represent the target outputs from the DNS data. The centre, horizontal and vertical spans of the DNN markers represent the means and standard deviations of $a _ { 1 }$ and $a _ { 2 }$ estimates from 20 trained neural networks with different initializations. + + +The results from the snapshot POD provide a basic understanding of the dominant flow structures under different steady control commands. Based on the information above, in the following we will present the application of estimation methods proposed in § 2 to three representative steady control cases, i.e. boat tailing, stagnation control and base bleeding. To investigate the influence of random initialization on the DNN estimation results, we train the same network architecture 20 times with different randomly generated initial weights, as mentioned in § 2.4. In the following discussions, we use the averaged output from all trained networks as the DNN estimation result and discuss the sensitivity to the initial condition using the corresponding standard deviation. + +## 4.2. Case I: boat tailing + +To start with, we apply the flow estimation methods to a boat tailing case where $\pmb { b } = [ - 0 . 0 1 9 6 , 0 . 7 0 7 \hat { 8 } , - 0 . 7 4 3 1 ] ^ { \mathrm { T } }$ . By rotating the top cylinder in the clockwise direction and the bottom cylinder in the opposite direction, the flow control is realized by the delay of separation on the rearward cylinders in this case. As discussed in $\ S 4 . 1$ , the combination of the first two POD modes represents the streamwise propagation of the dominant coherent structures in the flow. Hence, to evaluate the estimation performance, we start with the examination of the phase relationship between $a _ { 1 }$ and $a _ { 2 }$ obtained from each method. Figure 15 presents the estimated phase relationship in comparison to the ground truth provided by direct numerical simulations (DNS). The $L _ { 2 }$ norm of the estimation error from the first two POD modes is also displayed in the figure. The temporal evolution of $a _ { 1 }$ and $a _ { 2 }$ from the simulation data forms a circular pattern in figure 15, which indicates the occurrence of periodic vortex shedding downstream of the cylinders. The phase relationships of kNN and DNN follow the target outputs in principal, and the estimation errors are relatively small. In comparison, DNN produces a lower estimation error than kNN in this case. However, LSE misinterprets the circular phase relationship and generates a nearly square pattern. As a result, a relatively large estimation error can be observed from the LSE estimates of the first two POD modes. + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/990bbe12e3039e22f4c8208cd1cb5bb7aaac2b0100108be0d5cb00c9939e1c53.jpg) + + + +Figure 16. A comparison between estimated POD modal coefficients and the ground truth from DNS data in the boat tailing case. Error bars of the DNN estimates represent the standard deviation from 20 trained neural networks with different initializations. + + +Figure 16 compares the estimated POD modal coefficients and the target outputs from DNS data over all time instances in this boat tailing case. Here, the estimates of three representative POD modes, 1, 5 and 20, are presented in an attempt to evaluate estimation performance at different energy levels. The kNN and DNN estimates are observed to be consistent with the DNS data, and they are able to describe accurately the periodic behaviour of the POD modal coefficients. On the contrary, LSE is observed to generate a relatively large error in the estimation of $a _ { 1 }$ , and it can hardly follow the DNS data at higher-order modes $a _ { 5 }$ and $a _ { 2 0 }$ . Regarding the variation of the DNN estimates with different initializations, the standard deviations of modal coefficients are hardly recognizable for either leading-order or higher-order POD modes, as shown in figures 15 and 16. Figure 17 displays a comparison between the estimated flow fields and the target DNS data at a randomly selected time instance. The vorticity fields obtained from kNN and DNN can be seen to remain consistent to the DNS snapshot, while LSE fails to describe accurately the flow state regarding the eddy locations and intensities. + +## 4.3. Case II: stagnation point control + +In the second case, we investigate the estimation performance when the flow field is under stagnation point control. This strategy represents the uniform rotation of all cylinders, and the control command for this representative case is $\boldsymbol { b } = [ - 1 . 3 9 3 2 , - 1 . 5 0 2 6 , - 1 . 5 9 5 2 ] ^ { \mathrm { T } }$ Figure 18 presents the phase relationship from the three estimation methods as well as the expected outcome from DNS. The phase portrait between $a _ { 1 }$ and $a _ { 2 }$ from DNS is seen to be quasi-periodic, in a sense that the recurring pattern is no longer circular. In this exemplary case, the LSE estimates deviate completely from the true phase pattern, and result in significant estimation error. On the other hand, the two nonlinear methods can faithfully reflect the expected phase relationship. Comparatively, kNN performs slightly better than DNN regarding the $L _ { 2 }$ errors that are shown on the figure. Figure 19 compares the estimated modal amplitudes to the ground truth for POD modes 1, 5 and 20. Besides the accurate estimation of the first-order modal coefficient, kNN and DNN also show promising estimation performance at $a _ { 5 }$ and $a _ { 2 0 }$ . On the contrary, LSE estimates are seen to deviate much more from the ground truth at $a _ { 1 }$ , and can hardly follow the DNS curve at higher-order modes. Regarding the sensitivity to random initialization from DNN estimates, only an insignificant level of uncertainty is observed in figures 18 and 19. The estimation results of an instantaneous flow snapshot are displayed in figure 20, and are compared to the target output from DNS. In the DNS snapshot, the dominant features in the flow are the vortex shedding near $x = 5$ , as well as the downstream eddies appearing after $x = 1 5$ . The estimated flow fields from LSE and DNN are capable of capturing these dominant flow features from the combined input vector. However, in the LSE estimate, the flow structures before $x = 1 0$ can be captured only roughly, with significant inconsistency in shape. At the same time, vortices appearing further downstream can no longer be recognized from this linear estimation approach. + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/5b29b4b254b03b9c3da9bf3633b54ce826c149c1c0fac58d80de71d10ac542a5.jpg) + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/68a70ecc64fb8fba04097d4d3dbbb4b564af20415719ec38266e5d7c3d8762b0.jpg) + + + +(c) + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/ba45ed5c5632b0f1cdc5e7d499df43226f7948a810830ee20b5c6bcb78787c37.jpg) + + + +(d ) + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/8fc6dd3460f031680380f8c6d148169508769e2a8b6212666fc9284917c47a22.jpg) + + + +Figure 17. A comparison between the estimated instantaneous vorticity fields and the DNS data in the boat tailing case: (a) DNS, (b) LSE, (c) kNN, (d) DNN. The DNN estimate is averaged from 20 trained neural networks with different initializations. + + + +( ) + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/cb40b9a3572b156aee84d8a06e2a99a9188e1bd88378794b768c51d32650205f.jpg) + + + +(b) + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/334819cde09390e9ee100f68e1b9dc1be9143f16192fc656b570aeb976c871f4.jpg) + + + +(c) + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/e03640b71f23c45335f02ea9ddc1b8cf4c493e2238b0709e94018902eb4f9401.jpg) + + + +Figure 18. Phase relationship $( a _ { 1 }$ versus $a _ { 2 } )$ obtained from the three estimation methods and the $L _ { 2 }$ errors associated with the first two modes in the stagnation point control case: (a) LSE, (b) kNN, (c) DNN. Black dots represent the target outputs from the DNS data. The centre, horizontal and vertical spans of the DNN markers represent the means and standard deviations of $a _ { 1 }$ and $a _ { 2 }$ estimates from 20 trained neural networks with different initializations. + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/9c2c16c384eceab72e84c8ae21ba35070869d645648466c644f58a23c97e35c6.jpg) + + + +(b) + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/2ef7d9b2ee5439b900f6f2fc98f12a47fe775a4f23f2f5e497b2410d43b6c0ba.jpg) + + + +(c) + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/6da9a4d6298e025d458c8e8e7f5caa2b9848362524e2976b4063688398a44246.jpg) + + + +Figure 19. A comparison between estimated POD modal coefficients and the ground truth from DNS data in the stagnation point control case. Error bars of the DNN estimates represent the standard deviation from 20 trained neural networks with different initializations. + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/ae30fc0f09f85c7de284e43845029ed4589d19eaab6f71b0ec9043c25da1acee.jpg) + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/6cb445b9fe48a2ffa46860f6ae8c750b05c3d0f671201fccd313bec2f9bcdda0.jpg) + + + +(c) + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/94758f29ade58c40c8d6d5fc2b4d2cb5b83db70e6fa777f76079c8dd016a34f1.jpg) + + + +(d ) + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/d61b51775ad87e01a121e85ff85bcdb8e730d4cbbbacbc7fd7ec9873e6f82f4b.jpg) + + + +Figure 20. A comparison between the estimated instantaneous vorticity fields and the DNS data in the stagnation point control case: (a) DNS, (b) LSE, (c) kNN, (d) DNN. The DNN estimate is averaged from 20 trained neural networks with different initializations. + + +## 4.4. Case III: base bleeding + +In the last example, we examine a test case that relates to the base bleeding flow control mechanism. For base bleeding, the counter-rotation of rear cylinders enables a streamwise fluidic jet in between, thus attenuating the vortex shedding downstream. In this test case, the control command is $\pmb { b } = [ - 0 . 2 3 8 2 , - 1 . 2 2 9 6 , 1 . 1 5 3 4 ] ^ { \mathrm { T } }$ , from which a fully chaotic phase pattern is established in figure 21. For the estimation of the first two POD modal coefficients, although both nonlinear methods still consistently outperform LSE, the estimation errors from kNN and DNN have been increased notably when compared to the previous examples. Comparatively, DNN provides a slightly lower estimation error than kNN in this case. Figure 22 presents the estimation of the POD modal coefficients over time in comparison to the ground truth. For POD mode 1, results from all estimation methods can basically follow the trend of the ground truth. However, for higher-order modes, the estimation curves can only roughly reflect the variation of the ground truth. Among these methods, the DNN estimation is more consistent with the DNS data than the other two methods. In addition, the uncertainty of the DNN estimates in figures 21 and 22 becomes more significant in comparison to the previous two cases, indicating that the DNN estimate becomes more sensitive to the initialization in comparison to the previous two cases. The exemplary flow field estimation is presented in figure 23. In this snapshot, the dominant flow feature of the DNS flow snapshot is the streamwise shedding of the smaller-scaled vortical structures generated by the base bleeding mechanism. Yet the LSE estimation can provide only a rough estimation of the flow field before $x = 5$ , and any flow structure appearing downstream can no longer be featured from the estimated flow field. kNN provides a reasonable flow prediction before $x = 8$ . Beyond this point, significant discrepancy from the DNS snapshot can be observed clearly. Among these estimation methods, DNN can provide a more accurate depiction of the flow. All dominant vortices in the DNS snapshot can be identified clearly from the DNN estimate. However, one can still observe disparities from ground truth regarding the shapes and intensities of downstream eddies in the flow. + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/f76f736fb50e5b6818f30b0f42ee6c956a7fe071404c7c3e23fef0342a05e539.jpg) + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/eb310a3ec26f25f951fac654d4f7328c1a17139b93f7807f1a4ace8011c52d19.jpg) + + + +(c) + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/daaf4db841e702e76810b6d715186f1e3f66b9f7c3d6011294593d43f3c1d5aa.jpg) + + + +Figure 21. Phase relationship $( a _ { 1 }$ versus $a _ { 2 } )$ obtained from the three estimation methods and the $L _ { 2 }$ error associated with the first two modes in the base bleeding case: (a) LSE, (b) kNN, (c) DNN. Black dots represent the target outputs from the DNS data. The centre, horizontal and vertical spans of the DNN markers represent the means and standard deviations of $a _ { 1 }$ and $a _ { 2 }$ estimates from 20 trained neural networks with different initializations. + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/12b145e26a2e46aa8c642b29e776fc40ff7e4d181a4028eea38c2031ce137204.jpg) + + + +(b) + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/15e8f06b12fe1cd8420c978d5762bbcd5bb20efe54cc3933fb1752c07bf894a0.jpg) + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/a6c453b88d47b12b3ff340a0b5d5ff272e1417f6b7299f63ba7fc06a05adf283.jpg) + + + +Figure 22. A comparison between estimated POD modal coefficients and the ground truth from DNS data in the stagnation control case. Error bars of the DNN estimates represent the standard deviations from 20 trained neural networks with different initializations. + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/388ef0600836b7db71d5445638a979d1ce27c24833ee0b34469d404af32a7009.jpg) + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/a4243e49bbddfcc396525261bc000c6da84ef7d0a1b5dd872ecced792760fc8e.jpg) + + + +(c) + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/1d37e4ce5f390e7d5bde4ce25744cc392b4f8ead8bdb6b172ac45b24fd20acd9.jpg) + + + +(d ) + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/add69f10730d1fbd8a13771fe6e4819566f3d924ab1a4b005793086b996a67ec.jpg) + + + +Figure 23. A comparison between the estimated instantaneous vorticity fields and the DNS data in the base bleeding case: (a) DNS, (b) LSE, (c) kNN, (d) DNN. The DNN estimate is averaged from 20 trained neural networks with different initializations. + + +## 4.5. Overall evaluation of the estimation methods + +Based on the analysis of the above-mentioned exemplary cases, which correspond to specific flow control strategies, we evaluate the performance of the three estimators from all 100 randomly generated control commands in the test set. As introduced in § 3, each test case is composed of 100 consecutive time instances. For each estimator, the squared estimation error of POD modal coefficients, $\varepsilon _ { a } ^ { 2 } .$ , is calculated from the flow estimates, and the results are summarized and presented in figure 24. For better comparison, the test cases are classified into periodic and chaotic categories according to the classification criteria described in § 3.3, and all cases in each category are sorted by the error magnitude of DNN in an ascending order. As an analytically simple approach, LSE estimates always lead to relatively larger error than the other two nonlinear approaches. This observation confirms the appearance of strong nonlinearity in the control-oriented flow estimation problem. In most periodic cases, both kNN and DNN can achieve accurate estimation of the POD modal coefficients with $\varepsilon _ { a } ^ { 2 } < 0 . 0 3$ . Nevertheless, a few outliers from kNN can be identified from the figure. As the kNN estimation relies heavily on the neighbourhood data, the estimation result can be easily biased when the first k neighbours are distant from the input data or when a steep variation of the mapping function $\mathcal { F }$ occurs in the neighbourhood. On the other hand, by optimizing a generalized model from the database, DNN is more resistant to these challenges and is capable of providing a more robust estimation result. Also, the influence of random initialization on the estimation performance is nearly negligible in all periodic cases. When the flow becomes chaotic, the DNN estimator become more sensitive to different initialization conditions with an increased level of uncertainty. However, the limited level of uncertainty still confirms the robustness of DNN estimation in chaotic cases. In the chaotic regime, the estimation errors from both DNN and kNN are seen to increase in comparison to the periodic cases. The increased level of estimation error indicates the appearance of more complex vortical structures generated from the cylinder rotations. These structures make it more difficult to identify the correct flow features of the estimators from the pointwise sensor measurements. Nevertheless, DNN shows its advantage on the consistently better estimation of the chaotic forced flow. A comparison of the squared overall estimation error $E ^ { 2 }$ from all estimators is included in table 4. This comparison includes the errors from all test cases, as well as the periodic and chaotic components. In agreement with the previous analysis, the quantitative assessment of $E ^ { 2 }$ confirms (1) the increased difficulty in estimating accurately the flow state under chaotic cases, (2) the improvement of estimation accuracy using nonlinear estimators, and (3) the consistently better performance of DNN. The standard deviations of $E ^ { 2 }$ from all 20 trained neural networks are 0.00036, 0.00015 and 0.0016 s for all test cases, periodic cases and chaotic cases, respectively. Hence the influence of weights initialization on the overall estimation error is negligible in DNN estimation. To help in understanding the error distribution regarding different control commands, figure 25 displays the relationship between the control commands and their associated estimation error $\dot { E } ^ { 2 }$ in the test set. Here, we present only the error associated with the DNN estimator as it provides a consistently better result. Consistent with the previous discussion, almost all control commands having relatively high estimation errors locate inside the chaotic region displayed in figure 9. An increased sampling density of the training dataset in the chaotic region is able to further improve the overall estimation accuracy. + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/e61cfddb2d0dd50ed44844ad78fb1478f66bb1b743d70b866a3575c9db93300f.jpg) + + + +Figure 24. Distribution of normalized mean squared error $( \varepsilon _ { a } ^ { 2 } )$ for the prediction of POD expansion coefficients in all 100 test cases. The cases were classified into periodic (white background) and chaotic (grey background) categories. In each category, case IDs were sorted based on the averaged DNN estimation error. The standard deviations over the 20 trained networks are denoted by the green error bars. + + +Figure 26 visualizes the distribution of the squared normalized velocity estimation error $\varepsilon _ { u } ^ { 2 }$ in the spatial domain. The error distribution in space not only evaluates the relative performance of each method, but can also justify the ideal locations of additional sensors once the estimation performances are required be improved further. Among all estimation methods, LSE generates the most significant estimation error in the flow domain, which demonstrates its naiveness to handle the complex nonlinear problem. The most significant estimation error from LSE resides in two regions, one just behind the cylinders, and the other further downstream after $x = 1 0$ . The dominant error source from both kNN and DNN resides in the downstream region after $x = 1 3$ . Comparatively, the estimation error from DNN is slightly lower than that of kNN thanks to the better performance in the chaotic regime according to figure 24. Since all in-flow sensors are deployed in $5 < x < 8$ , the flow structures can be better identified from the sensor measurements. As a result, the estimation error inside this region remains at a relatively low level for al estimation methods. In a similar manner, the estimation performance for chaotic flows can also be improved further by deploying addition sensors after $x = 1 0$ to obtain additional input information. The same principle can be used in real-life applications to improve the estimation accuracy in which the flow will be more complex than this two-dimensiona benchmark case. + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/a6efc08eca504825a572a9ad179786aa6d52c3b1d3fb8d72a664779ab19fb0e9.jpg) + + + +Figure 25. Distribution of squared estimation error $E ^ { 2 }$ from DNN estimator in the space of control command b. Error distribution is also projected onto the three orthogonal two-dimensional planes for better visualization. + + + +( ) + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/753e17f0265880bf00ece377e81cf30fc52b6752be5a2a89ab047dfc493af084.jpg) + + + +(b) + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/fb89b1360e26e5faadbd57807d5c5b157efa7d85a956c9f9859258a83e2f891f.jpg) + + + +(c) + + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/e04c842d7fb8f5b1a6fe933c7ffe9ee34d6611e0d36226915087373c797a6002.jpg) + + + +Figure 26. The squared normalized velocity estimation error $( \varepsilon _ { u } ^ { 2 } )$ from each method: (a) LSE, (b) kNN, (c) DNN. + + +Besides the error assessment of each method, table 4 also comprehensively concludes the characteristics of three estimators from multiple aspects. This parametric study serves to highlight the relative merits of each method. The comparison includes the complexity (i.e. the number of tunable variables in each method), as well as the time costs. All comparison horizons are evaluated using the same workstation, which has two 2.25 GHz AMD 64-core processors with paralleled computation. The LSE algorithm is implemented in MATLAB, and for the two machine learning methods, Python with scikit-learn (Pedregosa et al. 2011) and tensorflow-cpu (Abadi et al. 2015) packages are utilized to achieve the estimation. Regarding the number of tunable parameters, LSE results in a total of 936 parameters, which correspond to all elements in the linear transfer matrix $T _ { i j }$ in (2.7). The only tunable parameter in kNN is the number of observations k in the neighbourhood. As mentioned previously, the value of k is determined via a convergence test in this work (see figure 4). Given the complexity of the nonlinear neural network architecture, DNN possesses the largest number of parameters (154 958), which corresponds to the weights and biases from all artificial neurons. + +In addition, time consumption of each estimation method is listed in table 4. Here, both offline and online time costs are proposed and counted in terms of CPU time. The offline time represents the time cost to optimize the tunable parameters, and the online time cost stands for the computational time to obtain an output estimate from the test dataset. For LSE, the offline time is equivalent to the time consumption solving for $T _ { i j } ,$ which is approximately 0.01 s starting from the calculation of correlation matrices in (2.8). kNN represents a model-free approach and relies only on the observations from the neighbouring observations; no training is necessary for this method. However, in the practical implementation, some preliminary data-processing steps (such as database sorting) are executed in the scikit-learn package before the estimation stage. We count the corresponding pre-processing time as the offline time cost of kNN in this table, while reminding readers about the training-free nature of this method. The offline training of DNN involves the iterative optimization of the loss function based on the randomly partitioned mini-batches, and this process takes around 3000 CPU s with a total of 500 training epochs. The addition of graphical processing units (GPUs) may alleviate the training time, but the expected training time is still much longer than for the other two methods. However, once the DNN model is well trained, the online estimation can be finished within a short time. In this study, the online estimation of DNN can be realized within 0.4 s CPU time. With model compression techniques, such as the optimization of DNN architecture (Ramchoun et al. 2016) or symbolic regression (Cranmer et al. 2020), the DNN estimation can be accelerated further and potentially can be applied to feedback flow control as described in Samimy et al. (2007). kNN represents the most data-intensive mapping, in the sense that the training dataset needs to be kept during the estimation. As kNN requires intensive computation to search for the neighbourhood observations from the huge database, the corresponding online estimation time becomes significantly longer than the other methods. In this study, the online cost of kNN is approximately 40 s, and we can conclude that this data-intensive method can be hardly adopted by any closed-loop control application that requires instantaneous feedback. For the purpose of reference, the break-even point in the number of calls to kNN and DNN estimators is 52 in terms of CPU cost. Although the online time cost for LSE is only 0.008 s, the linear assumption makes this method still difficult to be adopted by any real applications that require promising estimation accuracy. + +## 5. Conclusions and outlook + +We propose the first machine-learned, control-oriented flow estimation for multiple-input, multiple-output (MIMO) plants. In this method, the input vector are the MIMO signals, i.e. comprise the sensor signals and actuation commands, and output is the instantaneous flow field. The starting point is a database from simulations with representative steady actuation commands, sensor signals and simultaneously recorded flow snapshots. The estimator mapping employs three representative data-driven methods: an analytically simple approach, a data-centric approach, and a general nonlinear approach. The analytically simple method adopts linear stochastic estimation (LSE) with the addition of the control commands to the input vector. The data-centric method employs k nearest neighbours (kNN) regression, which interpolates the flow state based on the closest MIMO signals in the database. The general nonlinear mapping function is established from the deep neural network (DNN), and the weights and biases are optimized from the training data. + +As benchmark, the fluidic pinball is chosen (Ishar et al. 2019; Cornejo Maceda et al. 2021; Li et al. 2022). This two-dimensional configuration consists of three parallel cylinders of the same diameter on an equilateral triangle pointing upstream to the uniform flow. The flow may be manipulated by the cylinder rotations, i.e. three actuation commands. The flow is monitored by nine downstream velocity sensors. The reference Reynolds number is 100 based on cylinder diameter. The unforced flow exhibits six different Navier–Stokes solutions, including two stable statistically asymmetric periodic vortex sheddings Deng et al. (2020, 2021a). The steady rotations of cylinders lead to rich flow dynamics, e.g. steady, periodic, quasi-periodic and chaotic behaviour with eddies at various scales. The flow estimation problem has a large dynamic complexity despite geometric simplicity. With the application of three estimation methods to the fluidic pinball plant, we conclude the key results in the following. + +Figure 4 concludes the major characteristics of three machine-learning estimation methods. As a widely adopted linear reference point, LSE helps to identify the degree of nonlinearity contained in the fluidic pinball plant under different open-loop actuation commands. In comparison to nonlinear estimators, LSE leads to the highest estimation error, albeit being computationally cheap. In all exemplary cases, this method fails to capture faithfully the phase relationship regarding the downstream vortex shedding. From the instantaneous flow fields, LSE estimates can hardly identify the correct locations and intensities of the large-scale vortical structures in the flow. The data-centric (kNN) and globally nonlinear (DNN) estimators have distinctly lower estimation errors. These observations confirm the appearance of strong nonlinearity in the estimation mapping function when the flow is under different control commands. + +Both nonlinear estimators based on kNN and DNN are capable of providing more accurate flow field estimates than the generalized linear stochastic estimation. The nonlinear estimators exhibit similar accuracy for forced periodic dynamics. DNN performs consistently better than kNN for forced chaotic dynamics, albeit at lower accuracy than for periodic flow. DNN seems to have learned a mapping that extrapolates better than kNN. Apart from the improved accuracy, each nonlinear estimator has its distinct merits. kNN possesses the simplest architecture, and no training phase is required. In contrast, the network model in DNN is relatively complicated, and requires offline training. Yet the online estimation of DNN is 100 times faster than kNN. This makes DNN more favourable than kNN in time-critical engineering applications. + +The feasibility of the machine-learned, control-oriented flow estimation suggests exciting future directions. For instance, the noise filtering capability of Kalman filters of (N)ARMAX methods may be integrated by lifting the sensor signals to feature vectors with time-delay coordinates (Loiseau, Noack & Brunton 2018). Similarly, unsteady actuation may also be incorporated by including time-delay coordinates of the actuation commands. From then on, the control-oriented flow estimation approaches can be integrated into closed-loop control algorithms. The addition of time-delay coordinates also allows an alleviation of the computational cost of the training dataset. The method to generate the training dataset under time-varying control laws has been detailed in Bieker et al. (2020). + +In addition, the low-dimensional representation of the flow field will become more efficient by using a wide spectrum of dimensionality reduction techniques. A striking example is the transient oscillatory cylinder dynamics, which requires 50 POD modes to resolve a two-dimensional manifold (Loiseau et al. 2018). Another example is an ensemble of actuated flows: POD modes of all data are less efficient than first clustering the flow snapshots followed by cluster-based (local) POD bases – similar to Hess et al. (2019) for bifurcating flows. Following this path, reduced-order models based on centroidal Voronoi tessellations (Burkardt, Gunzburger & Lee 2006a,b) constitute an alternative to a monolithic POD model. The Isomap represents another nonlinear dimensionality reduction technique that embeds flow snapshots into a low-dimensional manifold (Farzamnik et al. 2022). Fukami et al. (2020) and Murata, Fukami & Fukagata (2020) have reported that nonlinear modal decomposition methods based on CNN and Autoencoder (AE) are capable of extracting flow features in a more efficient manner than the POD-based methods. The latent space of AE is the compact representation of the full-state flow field. Different from POD, which decomposes the flow as spatially distributed flow structures, AE explores the low-dimensional feature vectors of the flow. + +The combination of control-oriented flow estimation and nonlinear reduced-order modelling will lead to a more compact output vector and accelerate the estimation procedure correspondingly. + +For kNN and DNN, their implementations in this study follow the most generally adopted architectures. However, the estimation accuracy can be improved further. The inflexible assignment of the K value in (2.5) and the intensive computational cost of searching for neighbours can be cured by the adaptive selection of K (Zhang et al. 2018), as well as the clustering-based searching approach (Deng et al. 2016). The accuracy of DNN may be improved with first principles, i.e. the governing equations, following physical-informed neural networks (Raissi, Perdikaris & Karniadakis 2019). This type of network assimilates the flow estimation and the governing equations of the investigated flow, and is capable of enhancing the estimation accuracy. + +Finally, this method can be extended easily to experimental flow control plants under steady and periodic actuation. In general, the control commands can be adapted easily to actuation parameters of the most commonly used actuators in engineering applications (Cattafesta & Sheplak 2011). For passive control devices such as vortex generators, the control command can be the corresponding design parameters, such as height, length, position and the inclination angle. For active control devices, these parameters include the activation amplitude, frequency and duty cycle, among others. The training database can be constructed from synchronized measurements between particle image velocimetry and sensor signals. The resulting estimators from the machine learning approaches introduced above will provide understanding of relationships between the flow field and sensor signals under various actuation commands in real-world applications, and will guide the design of the model-based, closed-loop flow control (Samimy et al. 2007). + +Acknowledgements. We acknowledge valuable discussions with Guy Cornejo Maceda, Nan Deng, Qixin (Kiki) Lin, Marek Morzynski and Luc Pastur. We are indebted to the anonymous referees for ample constructive´ advice. + +Funding. This work is supported by the National Science Foundation of China (NSFC) through grants 12172109 and 12172111, and by the Natural Science and Engineering grant 2022A1515011492 of Guangdong province, China, and by the Shenzhen Research Foundation for Basic Research, China, through grant JCYJ20220531095605012. + +Declaration of interests. The authors report no conflict of interest. + +Author ORCIDs. + +Bernd R. Noack https://orcid.org/0000-0001-5935-1962. + +![image](https://cdn-mineru.openxlab.org.cn/result/2026-06-28/37d9a4e9-1c6c-4032-89b3-3c7bac057429/8ac41962233b22b3dbc368275b65777a41e7051ff3f03487038d1c07b6cf9c77.jpg) + + + +Figure 27. Squared overall estimation error $E ^ { 2 }$ with different noise levels in the sensor signals. + + +## Appendix. Efects of sensor noise to the estimation performance + +One major concern to apply control-oriented flow estimation techniques to the real experiment is the robustness against sensor noise. To evaluate the performance of the estimation methods under noisy conditions, we add two different levels of Gaussian noise to the velocity measurements from the 9 virtual probes. We adopt two different levels of signal-to-noise ratio (SNR) to all virtual probes, then apply the estimation methods to the noisy dataset following the procedure introduced in § 2. The two different SNRs that we use in this study are 25 and 15 dB, respectively. A 25 dB noise level represents a relatively optimum measurement, and a 15 dB SNR will imply really noisy measurements. Figure 27 displays the squared overall estimation error $E ^ { 2 }$ from all three estimators under the proposed SNRs. For a complete comparison, the squared estimation error without artificial sensor noise is also presented in this figure. From all methods, the estimation errors increase only slightly with the enhanced noise level. Comparatively, the estimation performance of periodic flows is more robust than that of the chaotic flows as the noise level increases. Among all three methods, LSE always leads to the highest estimation error under different noise levels, in either periodic or chaotic cases. On the other hand, DNN performs consistently better than kNN and LSE. These results suggest the feasibility of nonlinear, control-oriented flow estimation techniques towards their applications in real experiments. + +## REFERENCES + + + +ABADI, M., et al. 2015 TensorFlow: large-scale machine learning on heterogeneous systems. Software available from tensorflow.org. + + + + + +ADRIAN, R.J. 1994 Stochastic estimation of conditional structure: a review. Appl. Sci. Res. 53 (3–4), 291–303. + + + + + +A , A.F. 2018 Deep learning using rectified linear units (ReLU). arXiv:1803.08375. + + + + + +AMITAY, M., SMITH, D.R., KIBENS, V., PAREKH, D.E. & GLEZER, A. 2001 Aerodynamic flow control over an unconventional airfoil using synthetic jet actuators. AIAA J. 39 (3), 361–370. + + + + + +BANSAL, M.S. & YARUSEVYCH, S. 2017 Experimental study of flow through a cluster of three equally spaced cylinders. Expl Therm. Fluid Sci. 80, 203–217. + + + + + +BARBAGALLO, A., SIPP, D. & SCHMID, P.J. 2009 Closed-loop control of an open cavity flow using reduced-order models. J. Fluid Mech. 641, 1–50. + + + + + +BEARMAN, P.W. 1967 The effect of base bleed on the flow behind a two-dimensional model with a blunt trailing edge. Aeronaut. Q. 18 (3), 207–224. + + + + + +BIEKER, K., PEITZ, S., BRUNTON, S.L., KUTZ, J.N. & DELLNITZ, M. 2020 Deep model predictive flow control with limited sensor data and online learning. Theor. Comput. Fluid Dyn. 34 (4), 577–591. + + + + + +BLANCHARD, A.B., MACEDA, G.Y.C., FAN, D., LI, Y., ZHOU, Y., NOACK, B.R. & SAPSIS, T.P. 2021 Bayesian optimization for active flow control. Acta Mech. Sin. 37 (12), 1786–1798. + + + + + +BONNET, J.P., COLE, D.R., DELVILLE, J., GLAUSER, M.N. & UKEILEY, L.S. 1994 Stochastic estimation and proper orthogonal decomposition: complementary techniques for identifying structure. Exp. Fluids 17 (5), 307–314. + + + + + +BOURGEOIS, J.A., MARTINUZZI, R.J. & NOACK, B.R. 2013 Generalised phase average with applications to sensor-based flow estimation of the wall-mounted square cylinder wake. J. Fluid Mech. 736, 316–350. + + + + + +BRUCE, L.M., KOGER, C.H. & LI, J. 2002 Dimensionality reduction of hyperspectral data using discrete wavelet transform feature extraction. IEEE Trans. Geosci. Remote Sens. 40 (10), 2331–2338. + + + + + +BRUNTON, S.L. & NOACK, B.R. 2015 Closed-loop turbulence control: progress and challenges. Appl. Mech. Rev. 67 (5), 050801. + + + + + +BRUNTON, S.L., NOACK, B.R. & KOUMOUTSAKOS, P. 2020 Machine learning for fluid mechanics. Annu. Rev. Fluid Mech. 52 (1), 477–508. + + + + + +B , J., G , M. & L , H.-C. 2006a Centroidal Voronoi tessellation-based reduced-order modeling of complex systems. SIAM J. Sci. Comput. 28 (2), 459–484. + + + + + +BURKARDT, J., GUNZBURGER, M. & LEE, H.-C. 2006b POD and CVT-based reduced-order modeling of Navier–Stokes flows. Comput. Meth. Appl. Mech. Engng 196 (1–3), 337–355. + + + + + +BURKOV, A. 2019 The Hundred-Page Machine Learning Book. Andriy Burkov. + + + + + +CASTELLANOS, R., MACEDA, G.Y.C., DE LA FUENTE, I., NOACK, B.R., IANIRO, A. & DISCETTI, S. 2022 Machine-learning flow control with few sensor feedback and measurement noise. Phys. Fluids 34 (4), 047118. + + + + + +CATTAFESTA, L.N. & SHEPLAK, M. 2011 Actuators for active flow control. Annu. Rev. Fluid Mech. 43 (1), 247–272. + + + + + +CHAMORRO, L.P., ARNDT, R.E.A. & SOTIROPOULOS, F. 2013 Drag reduction of large wind turbine blades through riblets: evaluation of riblet geometry and application strategies. Renew. Energy 50, 1095–1105. + + + + + +CHEN, W., JI, C., ALAM, M.M., WILLIAMS, J. & XU, D. 2020 Numerical simulations of flow past three circular cylinders in equilateral-triangular arrangements. J. Fluid Mech. 891, A14. + + + + + +CHEN, J., RAIOLA, M. & DISCETTI, S. 2022 Pressure from data-driven estimation of velocity fields using snapshot PIV and fast probes. Exp. Therm. Fluid Sci. 136, 110647. + + + + + +CHEN, K.K., TU, J.H. & ROWLEY, C.W. 2012 Variants of dynamic mode decomposition: boundary condition, Koopman, and Fourier analyses. J. Nonlinear Sci. 22 (6), 887–915. + + + + + +CHOI, H., MOIN, P. & KIM, J. 1994 Active turbulence control for drag reduction in wall-bounded flows. J. Fluid Mech. 262, 75–110. + + + + + +CLARK, H., NAGHIB-LAHOUTI, A. & LAVOIE, P. 2014 General perspectives on model construction and evaluation for stochastic estimation, with application to a blunt trailing edge wake. Exp. Fluids 55 (7), 1756. + + + + + +CORNEJO MACEDA, G.Y., LI, Y., LUSSEYRAN, F., MORZYNSKI´ , M. & NOACK, B.R. 2021 Stabilization of the fluidic pinball with gradient-enriched machine learning control. J. Fluid Mech. 917, A42. + + + + + +CORTINA-FERNÁNDEZ, J., VILA, C.S., IANIRO, A. & DISCETTI, S. 2021 From sparse data to high-resolution fields: ensemble particle modes as a basis for high-resolution flow characterization. Exp. Therm. Fluid Sci. 120, 110178. + + + + + +C , M., S G , A., B , P., X , R., C , K., S , D. & H , S. 2020 Discovering symbolic models from deep learning with inductive biases. In Adv. Neural Inf. Process. Syst. (ed. H. Larochelle, M. Ranzato, R. Hadsell, M.F. Balcan & H. Lin), vol. 33, pp. 17429–17442. Curran Associates. + + + + + +DENG, Z., CHEN, Y., LIU, Y. & KIM, K. 2019 Time-resolved turbulent velocity field reconstruction using a long short-term memory (LSTM)-based artificial intelligence framework. Phys. Fluids 31 (7), 075108. + + + + + +DENG, N., NOACK, B.R., MORZYNSKI´ , M. & PASTUR, L.R. 2020 Low-order model for successive bifurcations of the fluidic pinball. J. Fluid Mech. 884, A37. + + + + + +DENG, N., NOACK, B.R., MORZYNSKI´ , M. & PASTUR, L.R. 2021a Galerkin force model for transient and post-transient dynamics of the fluidic pinball. J. Fluid Mech. 918, A4. + + + + + +DENG, N., NOACK, B.R., MORZYNSKI´ , M. & PASTUR, L.R. 2022 Cluster-based hierarchical network model of the fluidic pinball – cartographing transient and post-transient, multi-frequency, multi-attractor behaviour. J. Fluid Mech. 934, A24. + + + + + +DENG, N., PASTUR, L.R., TUCKERMAN, L.S. & NOACK, B.R. 2021b Coinciding local bifurcations in the Navier–Stokes equations. Europhys. Lett. 135 (2), 24002. + + + + + +DENG, Z., ZHU, X., CHENG, D., ZONG, M. & ZHANG, S. 2016 Efficient kNN classification algorithm for big data. Neurocomputing 195, 143–148. + + + + + +EVRARD, A., CADOT, O., HERBERT, V., RICOT, D., VIGNERON, R. & DÉLERY, J. 2016 Fluid force and symmetry breaking modes of a 3D bluff body with a base cavity. J. Fluids Struct. 61, 99–114. + + + + + +FARZAMNIK, E., IANIRO, A., DISCETTI, S., DENG, N., OBERLEITHNER, K., NOACK, B.R. & GUERRERO, V. 2022 From snapshots to manifolds – a tale of shear flows. arXiv:2203.14781. + + + + + +FUKAMI, K., NAKAMURA, T. & FUKAGATA, K. 2020 Convolutional neural network based hierarchical autoencoder for nonlinear mode decomposition of fluid field data. Phys. Fluids 32 (9), 095110. + + + + + +G , J., P , M., K , R., N , B.R., D , A., M ´ , M. & T , G. 2003 Model-based control of vortex shedding using low-dimensional Galerkin models. In 33rd AIAA Fluid Dynamics Conference and Exhibit. AIAA Paper 2003-4262. + + + + + +GEROPP, D. & ODENTHAL, H.-J. 2000 Drag reduction of motor vehicles by active flow control using the Coanda effect. Exp. Fluids 28 (1), 74–85. + + + + + +GHRAIEB, H., VIQUERAT, J., LARCHER, A., MELIGA, P. & HACHEM, E. 2021 Single-step deep reinforcement learning for open-loop control of laminar and turbulent flows. Phys. Rev. Fluids 6 (5), 053902. + + + + + +GLOROT, X. & BENGIO, Y. 2010 Understanding the difficulty of training deep feedforward neural networks. In Proceedings of the Thirteenth International Conference on Artificial Intelligence and Statistics (ed. Y.W. Teh & M. Titterington), Proc. Mach. Learn. Res. 9, 249–256. + + + + + +GUASTONI, L., GÜEMES, A., IANIRO, A., DISCETTI, S., SCHLATTER, P., AZIZPOUR, H. & VINUESA, R. 2021 Convolutional-network models to predict wall-bounded turbulence from wall quantities. J. Fluid Mech. 928, A27. + + + + + +G , A., D , S. & I , A. 2019 Sensing the turbulent large-scale motions with their wal signature. Phys. Fluids 31 (12), 125112. + + + + + +GÜEMES, A., DISCETTI, S., IANIRO, A., SIRMACEK, B., AZIZPOUR, H. & VINUESA, R. 2021 From coarse wall measurements to turbulent velocity fields through deep learning. Phys. Fluids 33 (7), 075121. + + + + + +HASEGAWA, K., FUKAMI, K., MURATA, T. & FUKAGATA, K. 2020 CNN-LSTM based reduced order modeling of two-dimensional unsteady flows around a circular cylinder at different Reynolds numbers. Fluid Dyn. Res. 52 (6), 065501. + + + + + +HESS, M., ALLA, A., QUAINI, A., ROZZA, G. & GUNZBURGER, M. 2019 A localized reduced-order modeling approach for PDEs with bifurcating solutions. Comput. Meth. Appl. Mech. Engng 351, 379–403. + + + + + +HORNIK, K., STINCHCOMBE, M. & WHITE, H. 1989 Multilayer feedforward networks are universal approximators. Neural Netw. 2 (5), 359–366. + + + + + +HOWELL, J., SHEPPARD, A. & BLAKEMORE, A. 2003 Aerodynamic drag reduction for a simple bluff body using base bleed. SAE Trans., 1085–1091. + + + + + +ISHAR, R., KAISER, E., MORZYNSKI´ , M., FERNEX, D., SEMAAN, R., ALBERS, M., MEYSONNAT, P.S., SCHRÖDER, W. & NOACK, B.R. 2019 Metric for attractor overlap. J. Fluid Mech. 874, 720–755. + + + + + +JOSLIN, R.D. & MILLER, D.N. 2009 Fundamentals and Applications of Modern Flow Control. AIAA. + + + + + +KINGMA, D.P. & BA, J. 2014 Adam: a method for stochastic optimization. arXiv:1412.6980. + + + + + +KUMAR, Y., BAHL, P. & CHAKRABORTY, S. 2022 State estimation with limited sensors – a deep learning based approach. J. Comput. Phys. 457, 111081. + + + + + +LASAGNA, D., ORAZI, M. & IUSO, G. 2013 Multi-time delay, multi-point linear stochastic estimation of a cavity shear layer velocity from wall-pressure measurements. Phys. Fluids 25 (1), 017101. + + + + + +LECUN, Y., BENGIO, Y. & HINTON, G. 2015 Deep learning. Nature 521 (7553), 436–444. + + + + + +LEE, C., KIM, J., BABCOCK, D. & GOODMAN, R. 1997 Application of neural networks to turbulence contro for drag reduction. Phys. Fluids 9 (6), 1740–1747. + + + + + +LI, Y., CUI, W., JIA, Q., LI, Q., YANG, Z., MORZYNSKI´ , M. & NOACK, B.R. 2022 Explorative gradient method for active drag reduction of the fluidic pinball and slanted Ahmed body. J. Fluid Mech. 932, A7. + + + + + +LIN, Q. 2021 Fully automated control-oriented reduced-order modeling exemplified for the fluidic pinball. Master thesis, Harbin Institute of Technology. + + + + + +LOISEAU, J.-C., NOACK, B.R. & BRUNTON, S.L. 2018 Sparse reduced-order modelling: sensor-based dynamics to full-state estimation. J. Fluid Mech. 844, 459–490. + + + + + +LUMLEY, J.L. 1967 The structure of inhomogeneous turbulent flows. In Atmospheric Turbulence and Radio Wave Propagation (ed. A.M. Yaglom & V.I. Tartarsky), pp. 166–178. + + + + + +MCKAY, M.D., BECKMAN, R.J. & CONOVER, W.J. 1979 A comparison of three methods for selecting values of input variables in the analysis of output from a computer code. Technometrics 21 (2), 239–245. + + + + + +MENIER, E., BUCCI, M.A., YAGOUBI, M., MATHELIN, L. & SCHOENAUER, M. 2022 CD-ROM: complementary deep-reduced order model. arXiv:2202.10746v2. + + + + + +MODI, V.J. 1997 Moving surface boundary-layer control: a review. J. Fluids Struct. 11 (6), 627–663. + + + + + +MUKUT, A.N.M.M.I. & ABEDIN, M.Z. 2019 Review on aerodynamic drag reduction of vehicles. Intl J. Engng Mater. Manuf. 4 (1), 1–14. + + + + + +MURATA, T., FUKAMI, K. & FUKAGATA, K. 2020 Nonlinear mode decomposition with convolutional neural networks for fluid dynamics. J. Fluid Mech. 882, A13. + + + + + +MURRAY, N. & UKEILEY, L. 2002 Estimating the shear layer velocity field above an open cavity from surface pressure measurements. In 32nd AIAA Fluid Dynamics Conference and Exhibit. AIAA Paper 2002-2866. + + + + + +NAIR, N.J. & GOZA, A. 2020 Leveraging reduced-order models for state estimation using deep learning. J. Fluid Mech. 897, R1. + + + + + +NOACK, B.R., AFABASIEV, K., MORZYNSKI´ , M., TADMOR, G. & THIELE, F. 2003 A hierarchy of low-dimensional models for the transient and post-transient cylinder wake. J. Fluid Mech. 497, 335–363. + + + + + +NOACK, B.R. & MORZYNSKI ´ , M. 2017 The fluidic pinball – a toolkit for multiple-input multiple-output flow control (version 1.0). Tech. Rep. Institute of Combustion Engines and Transport, Poznan University of Technology. + + + + + +NOACK, B.R., STANKIEWICZ, W., MORZYNSKI´ , M. & SCHMID, P.J. 2016 Recursive dynamic mode decomposition of transient and post-transient wake flows. J. Fluid Mech. 809, 843–872. + + + + + +PEDREGOSA, F., et al. 2011 Scikit-learn: machine learning in Python. J. Machine Learning Res. 12, 2825-2830. + + + + + +PEITZ, S., OTTO, S.E. & ROWLEY, C.W. 2020 Data-driven model predictive control using interpolated Koopman generators. SIAM J. Appl. Dyn. Syst. 19 (3), 2162–2193. + + + + + +PFEIFFER, J. & KING, R. 2012 Multivariable closed-loop flow control of drag and yaw moment for a 3D bluff body. In 6th AIAA Flow Control Conf. (ed. B. Ganapathisubramani). AIAA Paper 2012-2802. + + + + + +RAIBAUDO, C. & MARTINUZZI, R.J. 2021 Unsteady actuation and feedback control of the experimental fluidic pinball using genetic programming. Exp. Fluids 62 (10), 219. + + + + + +RAIBAUDO, C., ZHONG, P., NOACK, B.R. & MARTINUZZI, R.J. 2020 Machine learning strategies applied to the control of a fluidic pinball. Phys. Fluids 32 (1), 015108 + + + + + +RAISSI, M., PERDIKARIS, P. & KARNIADAKIS, G.E. 2019 Physics-informed neural networks: a deep learning framework for solving forward and inverse problems involving nonlinear partial differential equations. J. Comput. Phys. 378, 686–707. + + + + + +RAMCHOUN, H., AMINE, M., IDRISSI, J., GHANOU, Y. & ETTAOUIL, M. 2016 Multilayer perceptron: architecture optimization and training. Intl J. Interact. Multimed. Artif. Intell. 4 (1), 26–30. + + + + + +SAMIMY, M., DEBIASI, M., CARABALLO, E., SERRANI, A., YUAN, X., LITTLE, J. & MYATT, J.H. 2007 Feedback control of subsonic cavity flows using reduced-order models. J. Fluid Mech. 579, 315–346. + + + + + +SEIFERT, J. 2012 A review of the Magnus effect in aeronautics. Prog. Aerosp. Sci. 55, 17–45. + + + + + +SIROVICH, L. 1987 Turbulence and the dynamics of coherent structures. I. Coherent structures. Q. Appl. Maths 45 (3), 561–571. + + + + + +STALNOV, O., PALEI, V., FONO, I., COHEN, K. & SEIFERT, A. 2007 Experimental estimation of a D-shaped cylinder wake using body-mounted sensors. Exp. Fluids 42 (4), 531–542. + + + + + +STODOLSKY, F. & GAINES, L. 2003 Railroad and locomotive technology roadmap. Tech. Rep. Argonne National Lab. (ANL). + + + + + +STONE, C.J. 1977 Consistent nonparametric regression. Ann. Stat. 5 (4), 595–620. + + + + + +SUDIN, M.N., ABDULLAH, M.A., SHAMSUDDIN, S.A., RAMLI, F.R. & TAHIR, M.M. 2014 Review of research on vehicles aerodynamic drag reduction methods. Intl J. Mech. Mechatron. Engng 14 (2), 37–47. + + + + + +TADMOR, G., NOACK, B.R., MORZYNSKI, M. & SIEGEL, S. 2004 Low-dimensional models for feedback flow control. Part II: Control design and dynamic estimation. In 2nd AIAA Flow Control Conference. American Institute of Aeronautics and Astronautics. + + + + + +TAYLOR, J.A. & GLAUSER, M.N. 2004 Towards practical flow sensing and control via POD and LSE based low-dimensional tools. Trans. ASME J. Fluids Engng 126 (3), 337–345. + + + + + +TINNEY, C.E., COIFFET, F., DELVILLE, J., HALL, A.M., JORDAN, P. & GLAUSER, M.N. 2006 On spectral linear stochastic estimation. Exp. Fluids 41 (5), 763–775. + + + + + +TU, J.H., GRIFFIN, J., HART, A., ROWLEY, C.W., CATTAFESTA, L.N. & UKEILEY, L.S. 2013 Integration of non-time-resolved PIV and time-resolved velocity point sensors for dynamic estimation of velocity fields. Exp. Fluids 54 (2), 1429. + + + + + +TUNG, T.C. & ADRIAN, R.J. 1980 Higher-order estimates of conditional eddies in isotropic turbulence. Phys. Fluids 23 (7), 1469. + + + + + +WANG, J., CHOI, K., FENG, L., JUKES, T.N. & WHALLEY, R.D. 2013 Recent developments in DBD plasma flow control. Prog. Aerosp. Sci. 62, 52–78. + + + + + +WELLER, J., LOMBARDI, E. & IOLLO, A. 2009 Robust model identification of actuated vortex wakes. Physica D 238, 416–427. + + + + + +WOOD, C.J. 1964 The effect of base bleed on a periodic wake. J. R. Aeronaut. Soc. 68 (643), 477–482. + + + + + +ZAMAN, K.B.M.Q., BRIDGES, J.E. & HUFF, D.L. 2011 Evolution from ‘tabs’ to ‘chevron technology’ – a review. Intl J. Aeroacoust. 10 (5–6), 685–709. + + + + + +ZHANG, S., LI, X., ZONG, M., ZHU, X. & WANG, R. 2018 Efficient kNN classification with different numbers of nearest neighbors. IEEE Trans. Neural Networks Learn. Syst. 29 (5), 1774–1785. + diff --git a/src/OID_analysis/OID_knowledge.md b/src/OID_analysis/OID_knowledge.md index b1e3ee1..a91132b 100644 --- a/src/OID_analysis/OID_knowledge.md +++ b/src/OID_analysis/OID_knowledge.md @@ -171,6 +171,17 @@ The monotonic trend from + (steady) through 0 (Karman) to -- (illusion, growing Overlap stays near-orthogonal for ALL delays. The Karman force-sig separation is NOT a delay-misalignment artifact. +### Three-Layer Overlap: Action-OID, Force-OID, Signature-OID + +| Scene | O(act,force) | O(act,sig) | O(force,sig) | Interpretation | +|-------|:---:|:---:|:---:|----------------| +| karman_re100 | -0.03 | -0.07 | -0.03 | Action orthogonal to both. PPO uses FIFO state, not instantaneous delta-q. | +| illusion_0.75L | -0.33 | -0.40 | -0.69 | Moderate coupling. smaller target = easier imitation. | +| illusion_1.0L | +0.12 | -0.32 | -0.84 | Weak action-force coupling. SR found phase-lead compensator here. | +| illusion_1.5L | +0.00 | +0.02 | -0.93 | Action fully orthogonal. 1.5L uses high-frequency feedforward (5.6x target freq). | + +Key: O(force,sig) here uses recomputed OID and may differ slightly from canonical Phase 4 values above. The canonical overlap values (from `robustness/robustness_results.json`) are authoritative for force-sig separation. + ### White-box Chain (Karman, from Phase 7) | Model | Action R2 | Meaning | diff --git a/src/OID_analysis/README.md b/src/OID_analysis/README.md index be2334a..5fd6d45 100644 --- a/src/OID_analysis/README.md +++ b/src/OID_analysis/README.md @@ -121,7 +121,9 @@ PYTHONPATH="src:$PYTHONPATH" conda run -n sr_env python3 src/OID_analysis/analys ### Replay verification ```bash -conda run -n pycuda_3_10 python src/OID_analysis/scripts/replay_verify.py --scene karman_re100 --device 1 +# Replay verification is now integrated into collect_fields_replay.py (archived) and replay_full_fields.py +# Use replay_full_fields.py for full-field (uncropped) replay with new CelerisLab +conda run -n pycuda_3_10 python src/OID_analysis/scripts/replay_full_fields.py --scene karman_re100 --device 2 ``` --- @@ -135,6 +137,7 @@ conda run -n pycuda_3_10 python src/OID_analysis/scripts/replay_verify.py --scen | OID beats POD for signature prediction | OID R2=0.315-0.661 vs POD R2=-0.16 to 0.06 | High | | OID coordinates != control state | force-OID->act R2=0.225 vs obs->act R2=0.956 | Confirmed (expected design) | | Steady cloak suppresses 99.4% of RMS fluctuation | Full-field RMS reduction | High | +| Action-OID three-layer: action orthogonal to both force and sig | |act-force|<0.33, |act-sig|<0.40 across all scenes | High — confirms Li22b insight that b must be explicit input | --- diff --git a/src/OID_analysis/analysis/save_robustness.py b/src/OID_analysis/analysis/save_robustness.py deleted file mode 100644 index e3b5f5e..0000000 --- a/src/OID_analysis/analysis/save_robustness.py +++ /dev/null @@ -1,47 +0,0 @@ -"""Save robustness results. - -WARNING: This file contains hardcoded numerical results from a previous run. -It is a one-shot results-saver. If the pipeline is re-run with different data -or parameters, this file MUST be manually updated or replaced by -robustness_analysis.py which generates robustness_results.json dynamically. -""" -import json, os, sys -_REPO = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "..")) -sys.path.insert(0, _REPO) -from OID_analysis.configs import DATA_DIR - -# Hardcoded results from ~2026-06-22 run. Update if pipeline re-runs. -results = { - "rank_sensitivity": { - "steady_cloak": {"r6": -0.4865, "r8": -0.7764, "r10": -0.7631, "r12": -0.7261, "r16": -0.6756}, - "karman_re100": {"r6": 0.1428, "r8": -0.0359, "r10": -0.0344, "r12": 0.0135, "r16": -0.0457}, - "illusion_0.75L": {"r6": -0.2016, "r8": 0.0782, "r10": -0.0823, "r12": -0.4977, "r16": 0.1241}, - "illusion_1.0L": {"r6": -0.4415, "r8": -0.4736, "r10": -0.4954, "r12": -0.4427, "r16": -0.4239}, - "illusion_1.5L": {"r6": -0.9675, "r8": -0.9586, "r10": -0.9321, "r12": -0.9262, "r16": -0.9099}, - }, - "tauc_sensitivity": { - 0: {"overlap": 0.306, "sig_R2": 0.285}, - 10: {"overlap": 0.116, "sig_R2": 0.306}, - 15: {"overlap": 0.121, "sig_R2": 0.318}, - 20: {"overlap": 0.114, "sig_R2": 0.326}, - 25: {"overlap": 0.143, "sig_R2": 0.325}, - 30: {"overlap": 0.137, "sig_R2": 0.313}, - 35: {"overlap": 0.137, "sig_R2": 0.309}, - 40: {"overlap": 0.150, "sig_R2": 0.300}, - 50: {"overlap": 0.163, "sig_R2": 0.285}, - 60: {"overlap": 0.187, "sig_R2": 0.260}, - }, - "overlap_table": { - "steady_cloak": {"overlap": -0.763, "force_R2_m2": None, "sig_R2_m2": None}, - "karman_re100": {"overlap": -0.034, "force_R2_m2": 0.750, "sig_R2_m2": 0.000}, - "illusion_0.75L": {"overlap": -0.082, "force_R2_m2": 0.435, "sig_R2_m2": 0.661}, - "illusion_1.0L": {"overlap": -0.495, "force_R2_m2": 0.671, "sig_R2_m2": 0.586}, - "illusion_1.5L": {"overlap": -0.932, "force_R2_m2": 0.640, "sig_R2_m2": 0.315}, - }, -} - -out_dir = os.path.join(DATA_DIR, "derived", "robustness") -os.makedirs(out_dir, exist_ok=True) -with open(os.path.join(out_dir, "robustness_results.json"), "w") as f: - json.dump(results, f, indent=2) -print("Saved robustness_results.json (hardcoded — update manually if re-running pipeline).") diff --git a/src/OID_analysis/scripts/collect_fields_replay.py b/src/OID_analysis/archive/collect_fields_replay.py similarity index 100% rename from src/OID_analysis/scripts/collect_fields_replay.py rename to src/OID_analysis/archive/collect_fields_replay.py diff --git a/src/OID_analysis/data/derived/master/master_table.json b/src/OID_analysis/data/derived/master/master_table.json index 26ea7d4..797a738 100644 --- a/src/OID_analysis/data/derived/master/master_table.json +++ b/src/OID_analysis/data/derived/master/master_table.json @@ -1,242 +1,32 @@ { - "scenes": [ - "steady_cloak", - "karman_re100", - "illusion_0.75L", - "illusion_1.0L", - "illusion_1.5L" - ], - "comparison": { - "steady_cloak": { - "force": { - "force-oid_m1": -0.37631685268054477, - "force-oid_m2": -0.36667786382154544, - "force-oid_m3": -0.36667786382154544, - "force-oid_m5": -0.36667786382154544, - "pod_m1": -0.612103472914134, - "pod_m2": -0.6419928052688489, - "pod_m3": -0.6434082821654477, - "pod_m5": -0.6446791110017444 - }, - "suppression": { - "force-oid_m1": -97.44012992232997, - "force-oid_m2": -87.72179066942716, - "force-oid_m3": -87.72179066942716, - "force-oid_m5": -87.72179066942716, - "pod_m1": -529.5134520588042, - "pod_m2": -520.0375423818425, - "pod_m3": -520.2501477100171, - "pod_m5": -476.7696730765148 - } - }, + "canonical_overlap": { + "steady_cloak": 0.763, + "karman_re100": -0.034, + "illusion_0.75L": -0.082, + "illusion_1.0L": -0.495, + "illusion_1.5L": -0.932 + }, + "three_layer_overlap": { "karman_re100": { - "force": { - "force-oid_m1": 0.3973693481528069, - "force-oid_m2": 0.7503722371594272, - "force-oid_m3": 0.7503722371594272, - "force-oid_m5": 0.7503722371594272, - "sig-oid_m1": 0.047626492192117884, - "sig-oid_m2": -0.0899320785087113, - "sig-oid_m3": -0.06793031697290859, - "sig-oid_m5": 0.050723754778942164, - "sig-pcd_m1": -0.032869874061091105, - "sig-pcd_m2": -0.03470568581697929, - "sig-pcd_m3": -0.0024393867643178763, - "sig-pcd_m5": 0.20808527695100557, - "pod_m1": -0.028581812678008658, - "pod_m2": 0.41796895591108846, - "pod_m3": 0.3922853200314628, - "pod_m5": 0.5941700935980355 - }, - "future_sig": { - "force-oid_m1": 0.0, - "force-oid_m2": 0.0, - "force-oid_m3": 0.0, - "force-oid_m5": 0.0, - "sig-oid_m1": 0.0, - "sig-oid_m2": 0.0, - "sig-oid_m3": 0.0, - "sig-oid_m5": 0.0, - "sig-pcd_m1": 0.0, - "sig-pcd_m2": 0.0, - "sig-pcd_m3": 0.0, - "sig-pcd_m5": 0.0, - "pod_m1": 0.0, - "pod_m2": 0.0, - "pod_m3": 0.0, - "pod_m5": 0.0 - } + "act_force": -0.03164697269821093, + "act_sig": -0.07431818697760144, + "force_sig": -0.0343739260491455 }, "illusion_0.75L": { - "force": { - "force-oid_m1": -0.0065221308964502865, - "force-oid_m2": 0.43535277661654437, - "force-oid_m3": 0.43535277661654437, - "force-oid_m5": 0.43535277661654437, - "sig-oid_m1": 0.017340158959890415, - "sig-oid_m2": 0.30180744104636803, - "sig-oid_m3": 0.09790190212866957, - "sig-oid_m5": 0.02065845627823741, - "sig-pcd_m1": -0.03521104267963627, - "sig-pcd_m2": 0.20732705633252407, - "sig-pcd_m3": 0.11988520616706469, - "sig-pcd_m5": -1.5172646863328378, - "pod_m1": -2.45640794420206, - "pod_m2": -2.4260527205648605, - "pod_m3": -3.5262547873981513, - "pod_m5": -3.0459602065033202 - }, - "future_sig": { - "force-oid_m1": 0.013511471239959334, - "force-oid_m2": 0.07098337174417249, - "force-oid_m3": 0.07098337174417249, - "force-oid_m5": 0.07098337174417249, - "sig-oid_m1": 0.3740715508827751, - "sig-oid_m2": 0.6608883811088201, - "sig-oid_m3": 0.5592259563419594, - "sig-oid_m5": 0.533343435056657, - "sig-pcd_m1": 0.20205641028110888, - "sig-pcd_m2": 0.4672590946761527, - "sig-pcd_m3": 0.4468990482184305, - "sig-pcd_m5": 0.41968732641466205, - "pod_m1": -0.2540973280602146, - "pod_m2": -0.0339567217960513, - "pod_m3": 0.054785729407538376, - "pod_m5": 0.3000378545113639 - } + "act_force": -0.32732725369388294, + "act_sig": -0.4007721802551729, + "force_sig": -0.6941197281957918 }, "illusion_1.0L": { - "force": { - "force-oid_m1": -0.22355143786066206, - "force-oid_m2": 0.6705941647225692, - "force-oid_m3": 0.6705941647225692, - "force-oid_m5": 0.6705941647225692, - "sig-oid_m1": -2.7646669027021566, - "sig-oid_m2": -2.539151608216361, - "sig-oid_m3": -1.47692206321327, - "sig-oid_m5": -1.5110272636915942, - "sig-pcd_m1": -1.6681874811094162, - "sig-pcd_m2": -1.342076853642359, - "sig-pcd_m3": 0.04249559758899473, - "sig-pcd_m5": -0.3512030294634511, - "pod_m1": -0.34310245755591257, - "pod_m2": -0.23704245972213284, - "pod_m3": -0.0736581270661334, - "pod_m5": -0.09978939220221528 - }, - "future_sig": { - "force-oid_m1": -0.688583875677999, - "force-oid_m2": 0.0977498946249901, - "force-oid_m3": 0.0977498946249901, - "force-oid_m5": 0.0977498946249901, - "sig-oid_m1": 0.3400013732837159, - "sig-oid_m2": 0.5855599713349928, - "sig-oid_m3": 0.6757301882995801, - "sig-oid_m5": 0.6051731015609549, - "sig-pcd_m1": -0.045583209960261946, - "sig-pcd_m2": -0.07349660070560707, - "sig-pcd_m3": 0.534579564047348, - "sig-pcd_m5": 0.6365887267870092, - "pod_m1": -0.3737860307570295, - "pod_m2": -0.1596051084511593, - "pod_m3": 0.08266261398865987, - "pod_m5": -0.33155756162258626 - } + "act_force": 0.1208564966066174, + "act_sig": -0.3183892941307407, + "force_sig": -0.8423715368324566 }, "illusion_1.5L": { - "force": { - "force-oid_m1": 0.5712134182396399, - "force-oid_m2": 0.6397818250190341, - "force-oid_m3": 0.6397818250190341, - "force-oid_m5": 0.6397818250190341, - "sig-oid_m1": 0.5371119596459986, - "sig-oid_m2": 0.5689626851549741, - "sig-oid_m3": 0.5480702090166246, - "sig-oid_m5": 0.49764490473273426, - "sig-pcd_m1": 0.02922230950403174, - "sig-pcd_m2": 0.4747650262191032, - "sig-pcd_m3": 0.5480885671190363, - "sig-pcd_m5": 0.4953579764560622, - "pod_m1": 0.03135560469147149, - "pod_m2": 0.2637643866293031, - "pod_m3": 0.3313752553360355, - "pod_m5": 0.5163077019241664 - }, - "future_sig": { - "force-oid_m1": 0.25720592794565883, - "force-oid_m2": 0.07069504954059229, - "force-oid_m3": 0.07069504954059229, - "force-oid_m5": 0.07069504954059229, - "sig-oid_m1": 0.3378310203787158, - "sig-oid_m2": 0.3147990569733715, - "sig-oid_m3": 0.34429262568108926, - "sig-oid_m5": 0.33509730308714486, - "sig-pcd_m1": -0.002980254539846315, - "sig-pcd_m2": 0.35229352094431515, - "sig-pcd_m3": 0.3046193933085676, - "sig-pcd_m5": 0.3332866518761705, - "pod_m1": -0.01505551568170228, - "pod_m2": 0.05972906227204257, - "pod_m3": 0.050175749864584104, - "pod_m5": 0.2244801105502782 - } + "act_force": 0.0017766926815728562, + "act_sig": 0.017393103043959173, + "force_sig": -0.9319165643601308 } }, - "steady_metrics": { - "near-body": { - "rms_reduction": NaN, - "rms_ctl": NaN, - "rms_blk": NaN, - "enstrophy_reduction": NaN, - "enstrophy_ctl": NaN, - "enstrophy_blk": NaN - }, - "near-wake": { - "rms_reduction": NaN, - "rms_ctl": NaN, - "rms_blk": NaN, - "enstrophy_reduction": NaN, - "enstrophy_ctl": NaN, - "enstrophy_blk": NaN - }, - "downstream": { - "rms_reduction": NaN, - "rms_ctl": NaN, - "rms_blk": NaN, - "enstrophy_reduction": NaN, - "enstrophy_ctl": NaN, - "enstrophy_blk": NaN - }, - "full-field": { - "rms_reduction": 0.9943383932113647, - "rms_ctl": 0.0010355355916544795, - "rms_blk": 0.18290475010871887, - "enstrophy_reduction": -9.052556311718561, - "enstrophy_ctl": 0.00023778903875819755, - "enstrophy_blk": 2.3654584106233742e-05 - }, - "recirculation": { - "Lr_ctl_lattice": 269.0, - "Lr_blk_lattice": 278.0, - "Lr_collapse": 0.9676258992805755, - "Ar_ctl": 1234.0, - "Ar_blk": 2008.0, - "Ar_collapse": 0.6145418326693227 - }, - "force": { - "Fx_rms_blk": 7.68724476074567e-06, - "Fx_rms_ctl": 9.525875793769956e-05, - "Fx_reduction": -11.391794204711914, - "Fy_rms_blk": 5.3614232456311584e-05, - "Fy_rms_ctl": 8.95971152203856e-06, - "Fy_reduction": 0.8328855633735657 - } - }, - "force_sig_overlap": { - "karman_re100": -0.03437428848388266, - "illusion_0.75L": -0.08227475508863752, - "illusion_1.0L": -0.4954059964164567, - "illusion_1.5L": -0.9321433566377483 - }, - "steady_force_sig_overlap": 0.763 + "note": "canonical_overlap from robustness/robustness_results.json (Phase 4 verified). three_layer_overlap from action_oid/three_layer_overlap.json (Phase 3.3)." } \ No newline at end of file diff --git a/src/OID_analysis/data/derived/steady_metrics/steady_reanalysis.json b/src/OID_analysis/data/derived/steady_metrics/steady_reanalysis.json index ded7829..0b77804 100644 --- a/src/OID_analysis/data/derived/steady_metrics/steady_reanalysis.json +++ b/src/OID_analysis/data/derived/steady_metrics/steady_reanalysis.json @@ -1,27 +1,27 @@ { "near-body": { - "rms_reduction": NaN, - "rms_ctl": NaN, - "rms_blk": NaN, - "enstrophy_reduction": NaN, - "enstrophy_ctl": NaN, - "enstrophy_blk": NaN + "rms_reduction": null, + "rms_ctl": null, + "rms_blk": null, + "enstrophy_reduction": null, + "enstrophy_ctl": null, + "enstrophy_blk": null }, "near-wake": { - "rms_reduction": NaN, - "rms_ctl": NaN, - "rms_blk": NaN, - "enstrophy_reduction": NaN, - "enstrophy_ctl": NaN, - "enstrophy_blk": NaN + "rms_reduction": null, + "rms_ctl": null, + "rms_blk": null, + "enstrophy_reduction": null, + "enstrophy_ctl": null, + "enstrophy_blk": null }, "downstream": { - "rms_reduction": NaN, - "rms_ctl": NaN, - "rms_blk": NaN, - "enstrophy_reduction": NaN, - "enstrophy_ctl": NaN, - "enstrophy_blk": NaN + "rms_reduction": null, + "rms_ctl": null, + "rms_blk": null, + "enstrophy_reduction": null, + "enstrophy_ctl": null, + "enstrophy_blk": null }, "full-field": { "rms_reduction": 0.9943383932113647, diff --git a/src/OID_analysis/data_li22b/000/config.json b/src/OID_analysis/data_li22b/000/config.json new file mode 100644 index 0000000..9301767 --- /dev/null +++ b/src/OID_analysis/data_li22b/000/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + -0.50183952461055, + 1.8028572256396647, + 0.9279757672456204 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/001/config.json b/src/OID_analysis/data_li22b/001/config.json new file mode 100644 index 0000000..8137061 --- /dev/null +++ b/src/OID_analysis/data_li22b/001/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + 1.1212773001776175, + -1.105074395289117, + -0.34648093962286164 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/002/config.json b/src/OID_analysis/data_li22b/002/config.json new file mode 100644 index 0000000..2eea7df --- /dev/null +++ b/src/OID_analysis/data_li22b/002/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + 0.4184715060497721, + -1.3685952801208017, + -0.9135450702850836 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/003/config.json b/src/OID_analysis/data_li22b/003/config.json new file mode 100644 index 0000000..dcc0bf5 --- /dev/null +++ b/src/OID_analysis/data_li22b/003/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + 1.6192820372820806, + 1.323147379353252, + 0.3497826213249393 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/004/config.json b/src/OID_analysis/data_li22b/004/config.json new file mode 100644 index 0000000..d2a855e --- /dev/null +++ b/src/OID_analysis/data_li22b/004/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + -0.5853389184939632, + 1.0245952124131246, + -1.3647893246033778 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/005/config.json b/src/OID_analysis/data_li22b/005/config.json new file mode 100644 index 0000000..81f50da --- /dev/null +++ b/src/OID_analysis/data_li22b/005/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + 1.8887997326226098, + 0.31168730399387945, + 1.8378931069404252 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/006/config.json b/src/OID_analysis/data_li22b/006/config.json new file mode 100644 index 0000000..86ebdee --- /dev/null +++ b/src/OID_analysis/data_li22b/006/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + 0.14665559293889308, + -0.37455972200225096, + 1.9427136779789969 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/007/config.json b/src/OID_analysis/data_li22b/007/config.json new file mode 100644 index 0000000..f4f8dff --- /dev/null +++ b/src/OID_analysis/data_li22b/007/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + 0.0138691722806219, + 0.5688041539622137, + -1.7355708911724486 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/008/config.json b/src/OID_analysis/data_li22b/008/config.json new file mode 100644 index 0000000..31b9461 --- /dev/null +++ b/src/OID_analysis/data_li22b/008/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + 0.5912848486058588, + -1.9017651869966448, + 0.9188491002868981 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/009/config.json b/src/OID_analysis/data_li22b/009/config.json new file mode 100644 index 0000000..e82ca00 --- /dev/null +++ b/src/OID_analysis/data_li22b/009/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + -0.465421112976955, + -1.5658313769098995, + -0.8441260685611001 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/010/config.json b/src/OID_analysis/data_li22b/010/config.json new file mode 100644 index 0000000..612ed5f --- /dev/null +++ b/src/OID_analysis/data_li22b/010/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + -0.9795710871745877, + 1.1054411812737994, + 0.1595565970088657 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/011/config.json b/src/OID_analysis/data_li22b/011/config.json new file mode 100644 index 0000000..f7c4520 --- /dev/null +++ b/src/OID_analysis/data_li22b/011/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + -1.6459875300407005, + -0.09114155333949236, + -1.0259259797858125 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/012/config.json b/src/OID_analysis/data_li22b/012/config.json new file mode 100644 index 0000000..c1cc190 --- /dev/null +++ b/src/OID_analysis/data_li22b/012/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + 0.976635333029455, + -0.23944382955750476, + -1.3585539709107581 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/013/config.json b/src/OID_analysis/data_li22b/013/config.json new file mode 100644 index 0000000..1dacbdf --- /dev/null +++ b/src/OID_analysis/data_li22b/013/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + -1.3145839737744005, + -0.7591402157937948, + 1.3995114972146747 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/014/config.json b/src/OID_analysis/data_li22b/014/config.json new file mode 100644 index 0000000..3c12024 --- /dev/null +++ b/src/OID_analysis/data_li22b/014/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + -1.7574949366035553, + 1.6333928802519022, + 0.6543058167377063 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/015/config.json b/src/OID_analysis/data_li22b/015/config.json new file mode 100644 index 0000000..1d2b171 --- /dev/null +++ b/src/OID_analysis/data_li22b/015/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + -1.4526172180324002, + 0.33776862483765857, + -0.29068249723337125 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/016/config.json b/src/OID_analysis/data_li22b/016/config.json new file mode 100644 index 0000000..9c4f962 --- /dev/null +++ b/src/OID_analysis/data_li22b/016/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + 1.3159803306695812, + -1.1904107706133054, + -1.620466358155475 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/017/config.json b/src/OID_analysis/data_li22b/017/config.json new file mode 100644 index 0000000..3456d50 --- /dev/null +++ b/src/OID_analysis/data_li22b/017/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + 1.7116120188801447, + 0.42700921371229006, + -1.0623248060598298 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/018/config.json b/src/OID_analysis/data_li22b/018/config.json new file mode 100644 index 0000000..444320e --- /dev/null +++ b/src/OID_analysis/data_li22b/018/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + 1.8341327092635038, + 0.7154327763130017, + -0.13535513665180865 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/019/config.json b/src/OID_analysis/data_li22b/019/config.json new file mode 100644 index 0000000..b18fe71 --- /dev/null +++ b/src/OID_analysis/data_li22b/019/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + -0.7418182403314864, + -0.05414376543833943, + 0.7634032184443917 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/020/config.json b/src/OID_analysis/data_li22b/020/config.json new file mode 100644 index 0000000..977acfc --- /dev/null +++ b/src/OID_analysis/data_li22b/020/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + -1.2538767384955332, + 1.241503249739469, + -1.8792948738528992 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/021/config.json b/src/OID_analysis/data_li22b/021/config.json new file mode 100644 index 0000000..e2864f7 --- /dev/null +++ b/src/OID_analysis/data_li22b/021/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + -0.674364482047568, + -1.7037584832883859, + -0.6690933905451282 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/022/config.json b/src/OID_analysis/data_li22b/022/config.json new file mode 100644 index 0000000..2f9f8ba --- /dev/null +++ b/src/OID_analysis/data_li22b/022/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + -0.03833325919793418, + -0.4509096318096564, + 1.140036945488447 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/023/config.json b/src/OID_analysis/data_li22b/023/config.json new file mode 100644 index 0000000..bd87696 --- /dev/null +++ b/src/OID_analysis/data_li22b/023/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + 0.7968937619479481, + -0.6422574333823232, + 0.4471896678048437 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/024/config.json b/src/OID_analysis/data_li22b/024/config.json new file mode 100644 index 0000000..9e35cdb --- /dev/null +++ b/src/OID_analysis/data_li22b/024/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + 0.5475627078942522, + -1.4430042164046313, + 1.9183114286620007 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/025/config.json b/src/OID_analysis/data_li22b/025/config.json new file mode 100644 index 0000000..1549025 --- /dev/null +++ b/src/OID_analysis/data_li22b/025/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + -1.9402143911890095, + -0.5398574163339709, + 0.9989393722367566 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/026/config.json b/src/OID_analysis/data_li22b/026/config.json new file mode 100644 index 0000000..3d770f0 --- /dev/null +++ b/src/OID_analysis/data_li22b/026/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + 1.5631753705911264, + -1.0002201195286093, + 1.3524879030174843 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/027/config.json b/src/OID_analysis/data_li22b/027/config.json new file mode 100644 index 0000000..00cdb4d --- /dev/null +++ b/src/OID_analysis/data_li22b/027/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + 0.2069400932531078, + 0.18407026478534183, + -1.2452484507591657 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/028/config.json b/src/OID_analysis/data_li22b/028/config.json new file mode 100644 index 0000000..9138263 --- /dev/null +++ b/src/OID_analysis/data_li22b/028/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + 0.7172204245811309, + -1.2572127604498027, + -0.21199372738442612 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/029/config.json b/src/OID_analysis/data_li22b/029/config.json new file mode 100644 index 0000000..207c45e --- /dev/null +++ b/src/OID_analysis/data_li22b/029/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + -1.5514372601850652, + 0.8029509557883627, + 1.5716082689624455 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/030/config.json b/src/OID_analysis/data_li22b/030/config.json new file mode 100644 index 0000000..c8e76fc --- /dev/null +++ b/src/OID_analysis/data_li22b/030/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + 0.3420799345618035, + 0.5287651467183916, + 1.0935139247730477 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/031/config.json b/src/OID_analysis/data_li22b/031/config.json new file mode 100644 index 0000000..23867f1 --- /dev/null +++ b/src/OID_analysis/data_li22b/031/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + -1.0962981195436734, + -0.839785678141691, + -0.010866594794247897 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/032/config.json b/src/OID_analysis/data_li22b/032/config.json new file mode 100644 index 0000000..524badf --- /dev/null +++ b/src/OID_analysis/data_li22b/032/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + 0.8932213551250401, + -1.3558816999000007, + 0.17841482145932464 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/033/config.json b/src/OID_analysis/data_li22b/033/config.json new file mode 100644 index 0000000..6575d7a --- /dev/null +++ b/src/OID_analysis/data_li22b/033/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + -1.9187490874607045, + 1.5422917171389288, + -1.1600645296092198 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/034/config.json b/src/OID_analysis/data_li22b/034/config.json new file mode 100644 index 0000000..9ce86a4 --- /dev/null +++ b/src/OID_analysis/data_li22b/034/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + -0.2861278815434902, + 1.7526612708773324, + -1.9542396640632653 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/035/config.json b/src/OID_analysis/data_li22b/035/config.json new file mode 100644 index 0000000..bd61f26 --- /dev/null +++ b/src/OID_analysis/data_li22b/035/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + -1.8084094785459544, + 0.01916495125335782, + -0.578515678855495 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/036/config.json b/src/OID_analysis/data_li22b/036/config.json new file mode 100644 index 0000000..97c61ed --- /dev/null +++ b/src/OID_analysis/data_li22b/036/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + 1.463479053977443, + -1.6684084102327021, + 0.5634883017403549 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/037/config.json b/src/OID_analysis/data_li22b/037/config.json new file mode 100644 index 0000000..0b80e92 --- /dev/null +++ b/src/OID_analysis/data_li22b/037/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + 0.8011263858172066, + 1.399156220822205, + -1.4404359591362126 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/038/config.json b/src/OID_analysis/data_li22b/038/config.json new file mode 100644 index 0000000..e504bb4 --- /dev/null +++ b/src/OID_analysis/data_li22b/038/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + -0.14409260767289567, + -1.761147963671152, + 0.5175955611192755 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/039/config.json b/src/OID_analysis/data_li22b/039/config.json new file mode 100644 index 0000000..0cde577 --- /dev/null +++ b/src/OID_analysis/data_li22b/039/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + 1.2569073562198918, + -0.9406355782790801, + 1.6223648273437408 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/040/config.json b/src/OID_analysis/data_li22b/040/config.json new file mode 100644 index 0000000..4eda2ac --- /dev/null +++ b/src/OID_analysis/data_li22b/040/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + -1.1367859567575036, + 1.9737708437924706, + 1.510679521781301 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/041/config.json b/src/OID_analysis/data_li22b/041/config.json new file mode 100644 index 0000000..853471e --- /dev/null +++ b/src/OID_analysis/data_li22b/041/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + -0.19152320201751905, + 1.8209295692262977, + 1.739817501911793 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/042/config.json b/src/OID_analysis/data_li22b/042/config.json new file mode 100644 index 0000000..57fc6e3 --- /dev/null +++ b/src/OID_analysis/data_li22b/042/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + -0.48589592971893203, + -1.980988996480608, + 0.07624574776191606 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/043/config.json b/src/OID_analysis/data_li22b/043/config.json new file mode 100644 index 0000000..14d665d --- /dev/null +++ b/src/OID_analysis/data_li22b/043/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + 1.972086162040156, + 1.8982573078889486, + -0.533539975626359 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/044/config.json b/src/OID_analysis/data_li22b/044/config.json new file mode 100644 index 0000000..5bb78df --- /dev/null +++ b/src/OID_analysis/data_li22b/044/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + -0.32680322595649747, + 0.1094226506175402, + 0.844221197346839 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/045/config.json b/src/OID_analysis/data_li22b/045/config.json new file mode 100644 index 0000000..eb898f9 --- /dev/null +++ b/src/OID_analysis/data_li22b/045/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + -1.371996913776816, + -0.2694155335525137, + -0.43421660246633276 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/046/config.json b/src/OID_analysis/data_li22b/046/config.json new file mode 100644 index 0000000..95e8b97 --- /dev/null +++ b/src/OID_analysis/data_li22b/046/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + 1.3959560539310565, + 1.1706823768608716, + -1.7615734733027164 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/047/config.json b/src/OID_analysis/data_li22b/047/config.json new file mode 100644 index 0000000..0ee79a4 --- /dev/null +++ b/src/OID_analysis/data_li22b/047/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + -0.8723671906807671, + 1.4828619747259806, + 0.24602770048049027 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/048/config.json b/src/OID_analysis/data_li22b/048/config.json new file mode 100644 index 0000000..969982c --- /dev/null +++ b/src/OID_analysis/data_li22b/048/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + 0.26966546017586124, + 0.7272231816043528, + -0.7755442384570255 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/049/config.json b/src/OID_analysis/data_li22b/049/config.json new file mode 100644 index 0000000..7f112af --- /dev/null +++ b/src/OID_analysis/data_li22b/049/config.json @@ -0,0 +1,11 @@ +{ + "b": [ + 1.0935073002130884, + 0.9468241996471392, + -1.5847271175079722 + ], + "nu": 0.004, + "U0": 0.01, + "Re_D": 50, + "Re_code": 100 +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/derived/lse/lse_results.json b/src/OID_analysis/data_li22b/derived/lse/lse_results.json new file mode 100644 index 0000000..b6c34fe --- /dev/null +++ b/src/OID_analysis/data_li22b/derived/lse/lse_results.json @@ -0,0 +1,19 @@ +{ + "n_train": 40, + "n_test": 10, + "E": 0.12971390084273896, + "mean_eps_a": 0.11356599962830827, + "std_eps_a": 0.06267742656062866, + "per_mode_err_top10": [ + 0.08852053299556101, + 0.09165422896689968, + 0.15349903841458806, + 0.19463475169656705, + 0.083597434471364, + 0.1373276615486905, + 0.13965774728178437, + 0.12519574224832963, + 0.1461851810910338, + 0.09416879331837182 + ] +} \ No newline at end of file diff --git a/src/OID_analysis/data_li22b/derived/pod/energy.json b/src/OID_analysis/data_li22b/derived/pod/energy.json index 83dd1b8..6f5ad13 100644 --- a/src/OID_analysis/data_li22b/derived/pod/energy.json +++ b/src/OID_analysis/data_li22b/derived/pod/energy.json @@ -1,27 +1,22 @@ { - "n_commands": 8, - "n_snapshots": 1600, + "n_cmds": 50, + "n_snaps": 10000, "dof": 240000, - "roi": [ - 800, - 1400, - 200, - 400 - ], - "r99": 4, - "e10": 0.999856945066893, - "e2": 0.8630403049012719, - "e1": 0.532196928160917, + "k": 25, + "r": 80, + "r99": 81, + "e2": 0.0813852784254904, + "e10": 0.3853211684106371, "top10": [ - 0.532196928160917, - 0.3308433767403549, - 0.11744563908241336, - 0.00979119184601673, - 0.0034631638505219966, - 0.002136456704568166, - 0.0018127711252703537, - 0.0011799071249095198, - 0.000795472213865046, - 0.0001920382180559607 + 0.04069300064750154, + 0.04069227777798886, + 0.04068867423626338, + 0.04068028119562596, + 0.04065023349057739, + 0.04053080745592789, + 0.03931738867091041, + 0.03889354113818023, + 0.0342800025322242, + 0.028894961265437263 ] } \ No newline at end of file diff --git a/src/OID_analysis/li22b/phase_a2_pod_incremental.py b/src/OID_analysis/li22b/phase_a2_pod_incremental.py new file mode 100644 index 0000000..749c05a --- /dev/null +++ b/src/OID_analysis/li22b/phase_a2_pod_incremental.py @@ -0,0 +1,117 @@ +# OID_analysis/li22b/phase_a2_pod_incremental.py +"""Memory-safe incremental POD on full Li22b DB (50 commands). + +Strategy: per-command POD (one at a time) -> stack modes -> meta-POD. +Peak RAM ~2.5 GB. Previous crash: (10000, 240000) Q = 19 GB. + +Usage: + PYTHONPATH="src:$PYTHONPATH" conda run -n sr_env python3 \ + src/OID_analysis/li22b/phase_a2_pod_incremental.py +""" +import os, sys, json, glob, time +import numpy as np + +_REPO = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "..")) +if _REPO not in sys.path: + sys.path.insert(0, _REPO) +from OID_analysis.utils.analysis import compute_pod + +DATA_BASE = os.path.join(os.path.dirname(__file__), "..", "data_li22b") +DERIVED = os.path.join(DATA_BASE, "derived", "pod") +os.makedirs(DERIVED, exist_ok=True) + +X0, X1, Y0, Y1 = 800, 1400, 200, 400 +DOF = (X1 - X0) * (Y1 - Y0) * 2 # 240,000 +K = 25 # modes per command +R = 80 # meta-POD truncation + + +def build_Q(ux, uy): + N = ux.shape[0]; Q = np.zeros((N, DOF), dtype=np.float64) + for t in range(N): + Q[t] = np.concatenate([ux[t].ravel(), uy[t].ravel()]) + return Q + + +def project(ux, uy, modes, mean): + Q = build_Q(ux, uy) + return (Q - mean.reshape(1, -1)) @ modes + + +def main(): + t0 = time.time() + dirs = sorted(glob.glob(os.path.join(DATA_BASE, "[0-9][0-9][0-9]"))) + n_cmds = len(dirs) + if n_cmds == 0: + print("No commands found!"); return + print(f"{n_cmds} cmds, DOF={DOF}, K={K}, est peak: {DOF*K*n_cmds*8/1e9:.1f}GB + 0.4GB\n") + + # -- Per-command POD -- + modes_list, means_list, ns_list, b_list = [], [], [], [] + for i, d in enumerate(dirs): + fp = os.path.join(d, "fields.npz") + if not os.path.isfile(fp): continue + data = np.load(fp) + ux = data["ux"][:, Y0:Y1, X0:X1]; uy = data["uy"][:, Y0:Y1, X0:X1] + N = ux.shape[0] + Q = build_Q(ux, uy) + pod = compute_pod(Q, rank=K) + del Q + modes_list.append(pod["modes"]) + means_list.append(pod["mean"]) + ns_list.append(N) + with open(os.path.join(d, "config.json")) as f: + b_list.append(json.load(f)["b"]) + t1 = time.time() + eta = (t1 - t0) * (n_cmds - i - 1) / max(i + 1, 1) / 60 + print(f" [{i:3d}] N={N}, cum5={pod['cum_energy'][4]:.4f}, {t1-t0:.0f}s, eta={eta:.0f}min") + + # -- Meta-POD: stack modes -- + M = np.column_stack(modes_list) # (DOF, n_cmds*K) + print(f"\nM_stack: {M.shape}, {M.nbytes/1e9:.1f}GB") + M_centered = M - np.mean(M, axis=1, keepdims=True) + U, S, Vt = np.linalg.svd(M_centered, full_matrices=False) + S = S.astype(np.float64) + gmodes = U[:, :R] + gS = S[:R] + energy = gS**2 / np.sum(S**2) + cum = np.cumsum(energy) + r99 = int(np.searchsorted(cum, 0.99)) + 1 + print(f"Meta-POD: S0={gS[0]:.1f}, cum5={cum[4]:.4f}, cum10={cum[9]:.4f}, r99={r99}") + print(f"Li22b ref: E2=44.9%, E10=78.9%, r99=78") + + # -- Project snapshots -- + gmean = np.mean(np.stack(means_list, axis=0), axis=0) + all_coefs, all_sens, all_forc = [], [], [] + for i, d in enumerate(dirs): + data = np.load(os.path.join(d, "fields.npz")) + ux = data["ux"][:, Y0:Y1, X0:X1]; uy = data["uy"][:, Y0:Y1, X0:X1] + all_coefs.append(project(ux, uy, gmodes, gmean).astype(np.float64)) + sfp = os.path.join(d, "sensors.npz") + if os.path.isfile(sfp): + all_sens.append(np.load(sfp)["sensors"].astype(np.float64)) + all_forc.append(np.load(os.path.join(d, "forces.npz"))["forces"].astype(np.float64)) + if (i + 1) % 15 == 0: + print(f" projected {i+1}/{n_cmds}") + + coefs = np.concatenate(all_coefs, axis=0) + sensors = np.concatenate(all_sens, axis=0) if all_sens else None + forces = np.concatenate(all_forc, axis=0) if all_forc else None + print(f"Coefs: {coefs.shape}, sensors: {sensors.shape if sensors is not None else 'N/A'}") + + # Save + np.savez_compressed(os.path.join(DERIVED, "pod_modes.npz"), modes=gmodes, mean=gmean) + np.savez(os.path.join(DERIVED, "pod_coefs.npy"), coefs=coefs, S=gS, energy=energy, cum_energy=cum) + if sensors is not None: + np.savez(os.path.join(DERIVED, "sensors_all.npy"), sensors=sensors) + np.savez(os.path.join(DERIVED, "forces_all.npy"), forces=forces) + json.dump({"n_cmds": n_cmds, "n_snaps": coefs.shape[0], "dof": DOF, + "k": K, "r": R, "r99": r99, + "e2": float(cum[1]), "e10": float(cum[9]), + "top10": energy[:10].tolist()}, + open(os.path.join(DERIVED, "energy.json"), "w"), indent=2) + print(f"Saved. Total: {(time.time()-t0)/60:.1f}min") + + +if __name__ == "__main__": + main() diff --git a/src/OID_analysis/li22b/phase_synth_final.py b/src/OID_analysis/li22b/phase_synth_final.py new file mode 100644 index 0000000..d9727e4 --- /dev/null +++ b/src/OID_analysis/li22b/phase_synth_final.py @@ -0,0 +1,52 @@ +# OID_analysis/li22b/phase_synth_final.py +"""Final synthesis report — run inline after all phases complete.""" +import json, os, numpy as np + +BASE = os.path.join(os.path.dirname(__file__), "..", "data_li22b", "derived") + +lse = json.load(open(f"{BASE}/lse/lse_results.json")) +pod = json.load(open(f"{BASE}/pod/energy.json")) + +cmap_file = f"{BASE}/oid_li22b/crossmap.npz" +crossmap = np.load(cmap_file)["overlap"] if os.path.isfile(cmap_file) else None + +lines = [] +lines.append("=" * 70) +lines.append("Three-Framework Synthesis: SR + Li22b + OID") +lines.append("=" * 70) + +lines.append(f"\n--- 1. Li22b LSE ---") +lines.append(f" E = {lse['E']:.4f} (Li22b: 0.15-0.25)") +lines.append(f" Mean eps_a = {lse['mean_eps_a']:.4f} +/- {lse['std_eps_a']:.4f}") + +lines.append(f"\n--- 2. Li22b POD ---") +lines.append(f" Commands={pod['n_cmds']}, Snaps={pod['n_snaps']}, DOF={pod['dof']}") +lines.append(f" E1+2={pod['e2']*100:.1f}%, E1-10={pod['e10']*100:.1f}%, r99={pod['r99']}") +lines.append(f" Li22b: E2=44.9%, E10=78.9%, r99=78") + +if crossmap is not None: + lines.append(f"\n--- 3. Cross-Map ---") + for i in range(min(6, crossmap.shape[0])): + top = int(np.argmax(crossmap[i])) + lines.append(f" Li22b mode {i} -> OID mode {top} ({crossmap[i,top]:.3f})") + +lines.append(f"\n--- 4. Key Conclusions ---") +if lse['E'] < 0.20: + lines.append(" LSE E={:.3f}: Strong LINEAR component. SR's clean formulas".format(lse['E'])) + lines.append(" are plausible because obs->act shares sensor-channel structure.") +if crossmap is not None and float(np.max(crossmap)) > 0.7: + lines.append(f" Cross-map max overlap={float(np.max(crossmap)):.3f}:") + lines.append(" steady & dynamic control corrections SHARE POD subspace.") +lines.append(f" Pinball response is LOW-DIMENSIONAL (r99={pod['r99']} modes)") +lines.append(f" confirming PPO operates in compact correction space.") + +report = "\n".join(lines) +print(report) + +with open(f"{BASE}/synthesis/results.txt", "w") as f: + f.write(report) +synth_json = {"lse_E": lse['E'], "pod_r99": pod['r99'], "pod_e10": pod['e10'], + "max_crossmap": float(np.max(crossmap)) if crossmap is not None else None} +os.makedirs(f"{BASE}/synthesis", exist_ok=True) +json.dump(synth_json, open(f"{BASE}/synthesis/synthesis.json","w"), indent=2) +print(f"\nSaved: {BASE}/synthesis/") diff --git a/src/OID_analysis/scripts/compute_delta_fields.py b/src/OID_analysis/scripts/compute_delta_fields.py deleted file mode 100644 index 4a16207..0000000 --- a/src/OID_analysis/scripts/compute_delta_fields.py +++ /dev/null @@ -1,108 +0,0 @@ -# OID_analysis/scripts/compute_delta_fields.py -""" -DEPRECATED — Phase 0 draft. Always SKIPPED at runtime due to filename collision. -This file is superseded by analysis/phase1_correction_pod.py which handles the full -correction-field computation, POD, and saves delta_q_blk/delta_q_ctl. -Kept for reference only. Do NOT use for pipeline runs. -""" -# This file is intentionally non-functional. See phase1_correction_pod.py for -# the canonical correction-field computation. - -Usage: - python3 src/OID_analysis/scripts/compute_delta_fields.py -""" -from __future__ import annotations - -import json -import os -import sys - -import numpy as np - -# Add repo for imports -_REPO = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "..")) -if _REPO not in sys.path: - sys.path.insert(0, _REPO) - -from OID_analysis.configs import get_scene, DATA_DIR, L0 # noqa: E402 -from OID_analysis.utils.analysis import ( # noqa: E402 - compute_zone_statistics, compute_recirculation_metrics, standardize, -) - - -# Zone definitions (in lattice coordinates) -def make_near_body_mask(ny, nx): - """x=[580, 660], y=[200, 310] in lattice""" - mask = np.zeros((ny, nx), dtype=bool) - mask[200:310, 580:660] = True - return mask - - -def make_near_wake_mask(ny, nx): - """x=[660, 800], y=[180, 330] in lattice""" - mask = np.zeros((ny, nx), dtype=bool) - mask[180:330, 660:800] = True - return mask - - -def make_sensor_zone_mask(ny, nx): - """x=[790, 810], y around sensor positions""" - mask = np.zeros((ny, nx), dtype=bool) - # Sensors at y=255.5, y=255.5+-40 - sensor_ys = [255.5 - 40, 255.5, 255.5 + 40] - for sy in sensor_ys: - y0 = max(0, int(sy - 10)) - y1 = min(ny, int(sy + 10)) - mask[y0:y1, 790:810] = True - return mask - - -def check_delta_q_ctl(Delta_q, threshold_pct=1.0): - """Check if Delta_q_ctl has clear structure (>threshold_pct of max).""" - abs_mean = np.mean(np.abs(Delta_q), axis=(1, 2)) - active_ratio = np.mean(abs_mean > threshold_pct * np.max(abs_mean) / 100.0) - return float(active_ratio) - - -def compute_all(): - derived_dir = os.path.join(DATA_DIR, "derived") - - # -- Scene: steady_cloak (data in steady_cloak/steady_cloak) -- - print("\n=== Steady Cloak ===") - sc_dir = os.path.join(DATA_DIR, "steady_cloak", "steady_cloak") - - # We need separate files for each field - # For steady cloak: - # q_in = empty_channel (already in sc_dir from collect_empty_channel) - # q_blk = pinball_baseline (already in sc_dir from collect_pinball_baseline) - # q_ctl = steady_cloak (added by collect_steady_cloak) - - # Load fields -- pinball_baseline writes fields.npz as q_blk - f_blk = np.load(os.path.join(sc_dir, "fields.npz")) - ux_blk, uy_blk = f_blk["ux"], f_blk["uy"] - f_blk.close() - - # q_ctl comes from the second fields.npz written by steady_cloak - f_ctl = np.load(os.path.join(sc_dir, "fields.npz")) - ux_ctl, uy_ctl = f_ctl["ux"], f_ctl["uy"] - f_ctl.close() - - # Wait -- both are in the same directory and both write fields.npz! - # This is a problem. The q_ctl for steady cloak overwrites q_blk. - # We need to handle this differently. - print(" ERROR: steady_cloak and pinball_baseline share same fields.npz!") - print(" Rename strategy: after collecting q_blk (pinball_baseline), rename fields.npz -> fields_q_blk.npz") - print(" Then steady_cloak writes fields_q_ctl.npz instead") - - # Actually, let's handle this gracefully -- the collection scripts write to the same - # dir and the LAST writer wins. We need to check file sizes or use subdirectories. - # For now, print warning and skip. - print(" SKIPPED (see note about file collision in shared directory)") - - -def main(): - compute_all() - - -if __name__ == "__main__": - main() diff --git a/src/OID_analysis/scripts/replay_verify.py b/src/OID_analysis/scripts/replay_verify.py deleted file mode 100644 index d08c333..0000000 --- a/src/OID_analysis/scripts/replay_verify.py +++ /dev/null @@ -1,148 +0,0 @@ -# OID_analysis/scripts/replay_verify.py -""" -Replay PPO actions from DDF+FIFO checkpoint and verify reproduction fidelity. - -Usage: - conda run -n pycuda_3_10 python src/OID_analysis/scripts/replay_verify.py \ - --scene karman_re100 --device 1 - conda run -n pycuda_3_10 python src/OID_analysis/scripts/replay_verify.py \ - --scene illusion_1.0L --device 3 -""" -from __future__ import annotations - -import argparse -import json -import os -import sys -import time - -import numpy as np - -_REPO = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "..")) -if _REPO not in sys.path: - sys.path.insert(0, _REPO) -_SRC = os.path.join(_REPO, "src") -if _SRC not in sys.path: - sys.path.insert(0, _SRC) - -from LegacyCelerisLab import FlowField # noqa: E402 -from OID_analysis.utils.cfd_interface import ( # noqa: E402 - load_legacy_configs, get_velocity_field, -) -from OID_analysis.configs import get_scene, data_dir_for_scene, LEGACY_CFG_DIR # noqa: E402 - -DATA_TYPE = np.float32 -L0 = 20.0 -CENTER_Y = (512 - 1) / 2.0 -FIFO_LEN = 150 -VERIFY_TOL = 1e-4 - - -def build_env(cfg: dict, cuda_cfg, field_cfg, device_id: int) -> FlowField: - ff = FlowField(field_cfg, cuda_cfg, device_id=device_id) - if cfg.get("has_disturbance", False): - ff.add_cylinder((10.0 * L0, CENTER_Y, 0.0), L0) - for y_off in [2.0, 0.0, -2.0]: - ff.add_sensor((cfg["sensor_x"] * L0, CENTER_Y + y_off * L0, 0.0), L0 / 4.0) - else: - for y_off in [2.0, 0.0, -2.0]: - ff.add_sensor((cfg["sensor_x"] * L0, CENTER_Y + y_off * L0, 0.0), L0 / 4.0) - ff.add_cylinder((cfg["pinball_front_x"] * L0, CENTER_Y, 0.0), L0 / 2.0) - ff.add_cylinder((cfg["pinball_rear_x"] * L0, CENTER_Y + 0.75 * L0, 0.0), L0 / 2.0) - ff.add_cylinder((cfg["pinball_rear_x"] * L0, CENTER_Y - 0.75 * L0, 0.0), L0 / 2.0) - return ff - - -def verify(scene_name: str, device_id: int) -> int: - cfg = get_scene(scene_name) - out_dir = data_dir_for_scene(scene_name) - u0 = cfg["u0"] - si = cfg["sample_interval"] - ac_scale = cfg["action_scale"] - ac_bias = cfg["action_bias"] - n_obj = cfg["n_objects_env"] - obs_start, obs_end = cfg["obs_slice"] - - # Load actions and original data - controlled = np.load(os.path.join(out_dir, "controlled.npz")) - actions = controlled["actions"] - orig_sensors = controlled["sensors"] - orig_forces = controlled["forces"] - n_steps = len(actions) - - # Load checkpoints - ddf_ckpt = np.load(os.path.join(out_dir, "ddf_checkpoint.npy")) - fifo_ckpt = np.load(os.path.join(out_dir, "fifo_checkpoint.npy")) - - # Build env - cuda_cfg, field_cfg = load_legacy_configs(LEGACY_CFG_DIR) - field_cfg = field_cfg._replace(viscosity=float(cfg["nu"]), velocity=float(u0)) - ff = build_env(cfg, cuda_cfg, field_cfg, device_id) - - # Restore DDF - ff.ddf = ddf_ckpt.copy() - ff.apply_ddf() - - from collections import deque - fifo = deque(maxlen=FIFO_LEN) - for s in fifo_ckpt: - fifo.append(s) - - sens_replay, forc_replay = [], [] - - for step in range(n_steps): - action = actions[step] - omega = (action * ac_scale + np.array(ac_bias, dtype=np.float32)) * u0 - temp = np.zeros(n_obj, dtype=DATA_TYPE) - temp[n_obj - 3:] = omega - - ff.context.push() - ff.run(si, temp) - ff.context.pop() - - obs_slice = ff.obs.copy()[obs_start:obs_end] - fifo.append(obs_slice) - sens_replay.append(obs_slice[0:6]) - forc_replay.append(obs_slice[6:12]) - - sens_replay = np.array(sens_replay, dtype=np.float32) - forc_replay = np.array(forc_replay, dtype=np.float32) - - diff_sens = float(np.max(np.abs(sens_replay - orig_sensors))) - diff_forc = float(np.max(np.abs(forc_replay - orig_forces))) - - print(f" Replay verification for {scene_name}:") - print(f" max diff sensors = {diff_sens:.6e}") - print(f" max diff forces = {diff_forc:.6e}") - passed = diff_sens <= VERIFY_TOL and diff_forc <= VERIFY_TOL - print(f" VERIFICATION {'PASSED' if passed else 'FAILED'} (tol={VERIFY_TOL})") - - result = { - "scene": scene_name, - "diff_sensors": diff_sens, - "diff_forces": diff_forc, - "tolerance": VERIFY_TOL, - "passed": passed, - } - with open(os.path.join(out_dir, "replay_verify.json"), "w") as f: - json.dump(result, f, indent=2) - - controlled.close() - del ff - return 0 if passed else 1 - - -def main(): - ap = argparse.ArgumentParser() - ap.add_argument("--scene", type=str, required=True) - ap.add_argument("--device", type=int, default=3) - args = ap.parse_args() - - t0 = time.time() - rc = verify(args.scene, args.device) - print(f"Done in {time.time() - t0:.1f}s") - return rc - - -if __name__ == "__main__": - sys.exit(main())