Correction step

Updated but still non-solenoidal velocity field \(u_i^*\) is corrected to be divergence-free by solving a Poisson equation with respect to the scalar potential \(\phi\):

\[\frac{1}{J} \dif{}{\gcs{1}} \left( \frac{J}{\sfact{1}} \frac{1}{\sfact{1}} \dif{\phi}{\gcs{1}} \right) + \frac{1}{J} \dif{}{\gcs{2}} \left( \frac{J}{\sfact{2}} \frac{1}{\sfact{2}} \dif{\phi}{\gcs{2}} \right) + \frac{1}{J} \dif{}{\gcs{3}} \left( \frac{J}{\sfact{3}} \frac{1}{\sfact{3}} \dif{\phi}{\gcs{3}} \right) = \frac{1}{\Delta t} \dif{\vel{i}^*}{\gcs{i}}.\]

The eigenvalues are computed as follows:

src/fluid/compute_potential.c
383size_t myjsize = 0;
384size_t myjoffs = 0;
385sdecomp.get_pencil_mysize(info, pencil, SDECOMP_YDIR, c_gl_sizes[SDECOMP_YDIR], &myjsize);
386sdecomp.get_pencil_offset(info, pencil, SDECOMP_YDIR, c_gl_sizes[SDECOMP_YDIR], &myjoffs);
387*eval_ys = memory_calloc(myjsize, sizeof(double));
388for(size_t local_n = 0; local_n < myjsize; local_n++){
389  const size_t global_n = local_n + myjoffs;
390  (*eval_ys)[local_n] =
391    - 4. * pow(
392      sin( g_pi * global_n / r_gl_sizes[SDECOMP_YDIR] ),
393      2.
394    );
395}
src/fluid/compute_potential.c
398size_t myksize = 0;
399size_t mykoffs = 0;
400sdecomp.get_pencil_mysize(info, pencil, SDECOMP_ZDIR, c_gl_sizes[SDECOMP_ZDIR], &myksize);
401sdecomp.get_pencil_offset(info, pencil, SDECOMP_ZDIR, c_gl_sizes[SDECOMP_ZDIR], &mykoffs);
402*eval_zs = memory_calloc(myksize, sizeof(double));
403for(size_t local_n = 0; local_n < myksize; local_n++){
404  const size_t global_n = local_n + mykoffs;
405  (*eval_zs)[local_n] =
406    - 4. * pow(
407      sin( g_pi * global_n / r_gl_sizes[SDECOMP_ZDIR] ),
408      2.
409    );
410}

In the radial direction, tri-diagonal matrices are to be solved for each \(y\) and \(z\):

src/fluid/compute_potential.c
575// set center diagonal components
576for(size_t i = 1; i <= isize; i++){
577  tdm_c[i-1] =
578    - tdm_l[i-1]
579    - tdm_u[i-1]
580    + eval_y / HYXC(i  ) / HYXC(i  );
581}
582// boundary treatment (Neumann boundary condition)
583tdm_c[        0] += tdm_l[        0];
584tdm_c[isize - 1] += tdm_u[isize - 1];
585// solve
586tdm.solve(tdm_info, rhs + j * isize);
src/fluid/compute_potential.c
594// set center diagonal components
595for(size_t i = 1; i <= isize; i++){
596  tdm_c[i-1] =
597    - tdm_l[i-1]
598    - tdm_u[i-1]
599    + eval_y / HYXC(i  ) / HYXC(i  )
600    + eval_z / hz / hz;
601}
602// boundary treatment (Neumann boundary condition)
603tdm_c[        0] += tdm_l[        0];
604tdm_c[isize - 1] += tdm_u[isize - 1];
605// solve
606tdm.solve(tdm_info, rhs + (k * jsize + j) * isize);

After computing the scalar potential \(\phi\), the velocity field is corrected using its gradient:

\[\pder{\phi}{x_i} \approx \vec{e_{\gcs{1}}} \frac{1}{\sfact{1}} \dif{\phi}{\gcs{1}} + \vec{e_{\gcs{2}}} \frac{1}{\sfact{2}} \dif{\phi}{\gcs{2}} + \vec{e_{\gcs{3}}} \frac{1}{\sfact{3}} \dif{\phi}{\gcs{3}}.\]
src/fluid/correct/ux.c
48  BEGIN
49    const double hx = HXXF(i  );
50#if NDIMS == 2
51    const double psi_xm = PSI(i-1, j  );
52    const double psi_xp = PSI(i  , j  );
53    double * vel = &UX(i, j);
54#else
55    const double psi_xm = PSI(i-1, j  , k  );
56    const double psi_xp = PSI(i  , j  , k  );
57    double * vel = &UX(i, j, k);
58#endif
59    *vel -= prefactor / hx * (
60        - psi_xm
61        + psi_xp
62    );
63  END
src/fluid/correct/uy.c
48  BEGIN
49    const double hy = HYXC(i  );
50#if NDIMS == 2
51    const double psi_ym = PSI(i  , j-1);
52    const double psi_yp = PSI(i  , j  );
53    double * vel = &UY(i, j);
54#else
55    const double psi_ym = PSI(i  , j-1, k  );
56    const double psi_yp = PSI(i  , j  , k  );
57    double * vel = &UY(i, j, k);
58#endif
59    *vel -= prefactor / hy * (
60        - psi_ym
61        + psi_yp
62    );
63  END
src/fluid/correct/uz.c
28for(int k = 1; k <= ksize; k++){
29  for(int j = 1; j <= jsize; j++){
30    for(int i = 1; i <= isize; i++){
31      const double psi_zm = PSI(i  , j  , k-1);
32      const double psi_zp = PSI(i  , j  , k  );
33      UZ(i, j, k) -= prefactor / hz * (
34          - psi_zm
35          + psi_zp
36      );
37    }
38  }
39}