sandbox/MCVacher/test_harmonic.c

    Harmonic decomposition in a periodic oscillatory flow

    This example illustrates the use of harmonic.h on a simple, periodic, 2D oscillatory flow.

    We impose a time-periodic inlet velocity on both the left and right sides of a 2D domain.
    The goal is to demonstrate how the harmonic decomposition separates different frequency components of the velocity field.

    Simulation

    #include "grid/multigrid.h"
    #include "navier-stokes/centered.h"
    #include "harmonic.h"
    
    double Re;
    double U0;
    
    double omegas[3];
    
    const double omega0 = 2.*pi;
    
    face vector muv[];
    
    FILE * fpmax;
    
    int main() {
    
      Re = 1.;
      U0 = 0.1;
      L0 = 1.; 
    
      TOLERANCE = 1e-3 [*];

    Periodic-like oscillations are imposed on both left and right sides.

      u.n[bottom] = dirichlet(0.);
      u.t[bottom] = dirichlet(0.);
    
      u.n[top] = dirichlet(0.);
      u.t[top] = dirichlet(0.);
    
      u.n[left]  = dirichlet(U0*sin(omega0*1.0*t) * 4.*y/L0 * (1. - y/L0));
      u.n[right] = dirichlet(U0*sin(omega0*1.0*t) * 4.*y/L0 * (1. - y/L0));
      u.t[right] = neumann(0.);
    
      N = 128;
      origin (0, 0);  // set the origin
      init_grid(N);
    
      fpmax = fopen("log.dat", "w");
    
      mu = muv;
    
      run();
    }

    We define the two frequencies that will be analysed using harmonic.h.

    event init (t = 0) {
      omegas[0] = omega0*1.0; 
      omegas[1] = omega0*1.5;  
      omegas[2] = 0.0;           // sentinel value for harmonic.h
    }
    
    event properties (i++) {
      foreach_face()
        muv.x[] = fm.x[] * U0 * L0 / Re;
    }
    
    event logfile (i++) { 
      fprintf (stderr, "%d %g\n", i, t);
      fprintf (fpmax, "%d %g\n", i, t);
    }

    The function harmonic_decomposition() (from harmonic.h) performs a least-squares regression of a scalar or vector field — here, u_x — over a set of prescribed angular frequencies \omega_i.

    It fits the temporal signal at each grid point as: \tilde{u_x}(x,y,t) = Z(x,y) + \sum_i [A_i(x,y)\cos(\omega_i t) + B_i(x,y)\sin(\omega_i t)]

    where A_i and B_i are spatial fields representing the local amplitude and phase of each mode.

    event harmonic_analysis (t += 0.01; t <= 5) {
      harmonic_decomposition(u.x, t, omegas);
    }
    
    event profile (t = end) {
      printf ("----- END -----\n");
    }
    
    event ppm_output (t = 0; t += 0.01; t <= 5) {
    
      char name[80];
      sprintf (name, "uX.mp4");
      output_ppm (u.x, file = name, n = 512, min = -0.1, max = 0.1, linear = true);
    
      // amplitude for mode 1 (ω₁)
      scalar amp_mode_1[];
      int k1 = 0;
      foreach()
        amp_mode_1[] = sqrt(sq(val(u.x.harmonic.A[k1])) + sq(val(u.x.harmonic.B[k1])));
      boundary ({amp_mode_1});
      char name_u_1[80];
      sprintf(name_u_1, "u_amp_1.mp4");
      output_ppm(amp_mode_1, file = name_u_1, n = 512, min = 0, max = 0.1, linear = true);
    
      // amplitude for mode 2 (ω₂)
      scalar amp_mode_2[];
      int k2 = 1;
      foreach()
        amp_mode_2[] = sqrt(sq(val(u.x.harmonic.A[k2])) + sq(val(u.x.harmonic.B[k2])));
      boundary ({amp_mode_2});
      char name_u_2[80];
      sprintf(name_u_2, "u_amp_2.mp4");
      output_ppm(amp_mode_2, file = name_u_2, n = 512, min = 0, max = 0.1, linear = true);
    }

    Visualization

    Horizontal velocity field

    Projection of the velocity on mode #1

    Projection of the velocity on mode #2

    Interpretation of the harmonic decomposition

    The harmonic analysis produces maps of the amplitude associated with each tested frequency \omega_i.

    A strong, nearly time-independent amplitude field indicates that the corresponding frequency is dominant in the flow — meaning the local velocity oscillates periodically with that frequency.

    For instance, in this example:

    • The mode at \omega_1 = 2\pi corresponds to the imposed oscillation from the boundaries. Its amplitude field shows where the oscillation penetrates into the domain.
    • The mode at \omega_2 = 3\pi corresponds to a higher harmonic. Its amplitude rapidly goes to nearly zero.