sandbox/acastillo/output_fields/spectra/spectra.h
Horizontal spectra on planes
Shell-averaged spectra of a list of fields, on one or more planes of constant z. For a bi-periodic domain the planes cover one period exactly, so the transform needs no window and no detrending – unlike the inhomogeneous direction, where a Fourier spectrum would not be meaningful.
Sample at the finest grid size, m = 1 << maxlevel,
on planes inside the finest region. That is the only lattice whose
points are cell centres: with a ratio N/m the query point is a cell centre only
when the ratio is odd, and on a power-of-two grid the sole odd ratio is
1. Any other choice returns one arbitrarily chosen child cell, displaced
by up to half a cell, and on an adaptive grid that displacement varies
across the plane – position-dependent jitter rather than a rigid shift,
so it does not cancel in |\hat
c|^2.
Usage
vector u[];
spectrum_vector_stack (u, "spectra_u.h5", -0.5, 0.5, 32, 1 << MAXLEVEL,
X0, X0 + L0, Y0, Y0 + L0, "a", SPECTRA_HDF5);see, also the tests in tests_spectra/: the transform and binning in test_spectra_modes.c, the sampling rule stated above in test_spectra_amr.c, and the two writers in test_spectra_ascii.c and test_spectra_hdf5.c.
#include "spectra_shell.h"
#include "spectra_output.h"Spectra on nz planes evenly spaced across
[hmin, hmax], each snapped to a cell centre.
format picks the writer; mode applies to ASCII
only, since the HDF5 file always appends along its time axis.
Keep [hmin, hmax] inside the refined region and
m at the finest grid size, or the lattice stops landing on
cell centres. Use a fixed nz rather than one plane per
cell, so the block shape does not change as that region grows; the
heights are in the output, so rescaling them is a post-processing
choice.
mode defaults to append, so repeated runs in one
directory accumulate blocks – as the profile writers do.
void spectrum_scalar_stack (scalar * list,
const char * filename = "spectra.asc",
double hmin = 0., double hmax = 0.,
int nz = 1,
int m = N,
double xmin = X0, double xmax = X0 + L0,
double ymin = Y0, double ymax = Y0 + L0,
const char * mode = "a",
int format = SPECTRA_ASCII)
{
int len = list_len (list), nk = nshells (m, m), holes = 0;
double * E = malloc ((size_t) nz*len*nk*sizeof(double));
double * z = malloc ((size_t) nz*sizeof(double));
for (int iz = 0; iz < nz; iz++) {
z[iz] = snap_to_cell (nz > 1 ? hmin + (hmax - hmin)*(iz + 0.5)/nz : hmin, m);
holes += spectrum_plane (list, E + (size_t) iz*len*nk, z[iz],
xmin, xmax, ymin, ymax, m);
}
if (holes && pid() == 0)
fprintf (stderr, "spectrum_scalar_stack: %d points unfilled over %d planes\n",
holes, nz);
#ifdef HAVE_HDF5
if (format == SPECTRA_HDF5)
write_spectrum_block_hdf5 (filename, list, E, z, nz, nk, m, hmin, hmax);
else
#endif
write_spectrum_block_ascii (filename, mode, list, E, z, nz, nk, m,
hmin, hmax);
free (E);
free (z);
}A single plane, as one row block of the above.
void spectrum_scalar_plane (scalar * list,
const char * filename = "spectra.asc",
double h = 0.,
int m = N,
double xmin = X0, double xmax = X0 + L0,
double ymin = Y0, double ymax = Y0 + L0,
const char * mode = "a",
int format = SPECTRA_ASCII)
{
spectrum_scalar_stack (list, filename, h, h, 1, m,
xmin, xmax, ymin, ymax, mode, format);
}Per-component spectra of a vector. The total and any horizontal/vertical split follow by summing in post-processing.
void spectrum_vector_stack (vector u,
const char * filename = "spectra_u.asc",
double hmin = 0., double hmax = 0.,
int nz = 1,
int m = N,
double xmin = X0, double xmax = X0 + L0,
double ymin = Y0, double ymax = Y0 + L0,
const char * mode = "a",
int format = SPECTRA_ASCII)
{
spectrum_scalar_stack ({u.x, u.y, u.z}, filename, hmin, hmax, nz, m,
xmin, xmax, ymin, ymax, mode, format);
}
void spectrum_vector_plane (vector u,
const char * filename = "spectra_u.asc",
double h = 0.,
int m = N,
double xmin = X0, double xmax = X0 + L0,
double ymin = Y0, double ymax = Y0 + L0,
const char * mode = "a",
int format = SPECTRA_ASCII)
{
spectrum_vector_stack (u, filename, h, h, 1, m,
xmin, xmax, ymin, ymax, mode, format);
}
