# Postprocessor

The postprocessor is responsible for converting the output (snapshots of flow fields, and accumulated statistics) created at run time by `solver` into usable data. It can be extended to compute project-specific quantities on a case-by-case basis.
Parallel execution is supported on CPUs only: since the computational demand of `postproc` is limited, parallelism is only required to access large quantities of memory.
`postpoc` works with the same logic of `solver` (indeed, it `USE`s the same `io.cpl` to carry out most of its input-output operations), and creates VTK legacy files for visualization.
Currently, both rectilinear and unstructured VTK formats are supported. 


## Configuration of `settings.in`

| **Name**                       | **Values** | **Description** |
|--------------------------------|------------|-----------------|
| **`useRestart`**       | `YES`/`NO`    | Whether simulation uses restart.   |
| **`useStatsRestart`**  | `YES`/`NO`    | Whether statistics use restart.    |
| **`saveRestart`**      | `YES`/`NO`    | Whether simulation saves restart.  |
| **`saveField`**        | `YES`/`NO`    | Whether simulation saves snapshots. |
| **`calcStats`**        | `YES`/`NO`    | Whether simulation computes statistics. |
| **`writeRestartFreq`** | `<timesteps>` | How often (in timesteps) restart is saved. |
| **`writeFieldFreq`**   | `<timesteps>` | How often (in timesteps) a snapshot is saved. |
| **`updateStatsFreq`**  | `<timesteps>` | How often (in timesteps) statistics are updated. |
| **`tFirstRestart`**    | `<t>`         | When to save the first restart. |
| **`tFirstField`**      | `<t>`         | When to save the first snapshot. |
| **`tStartStatsCalc`**  | `<t>`         | When to start accumulating statistics. |
| **`statsNames`**       | See below     | List of statistics to be computed. |

**Table**: the `INPUT_OUTPUT` section of `settings.in`


## Flow statistics

`solver` contains code for computing simple, predefined flow statistics at run time, namely first and second statistical moments of velocity and pressure fluctuations. More complex statistics can be computed *a posteriori*, by going through the snapshots database. 

Since the code is general, only time-averaging is used, whereas averaging over homogeneous direction can be done *a posteriori*. This makes computing the full set of statistics quite memory- and disk-intensive even in simple cases. 
By default, statistics are computed and accumulated in single precision. Double precision is enabled by setting the macro `STATSIZE_IS_DOUBLE` in `headers.cpl`. Moreover, in `settings.in` one can select an arbitrary subset of the 13 available statistics, by filling in the variable `statsNames`. When dependencies are violated, a runtime error is triggered. 

| | Quantity                                             | ID | Dependency                                  |
|-|-------------------------------------------------------|----|---------------------------------------------|
|1| \( \overline{u} \)                                    |`um`|  -                                          |
|2| \( \overline{v} \)                                    |`vm`|  -                                          |
|3| \( \overline{w} \)                                    |`wm`|  -                                          |
|4| \( \overline{p} \)                                    |`pm`|  -                                          |
|5| \( \overline{u'v'} \)                                 |`uv`| \( \overline{u}, \overline{v} \)            |
|6| \( \overline{u'w'} \)                                 |`uw`| \( \overline{u}, \overline{w} \)            |
|7| \( \overline{v'w'} \)                                 |`vw`| \( \overline{v}, \overline{w} \)            |
|8| \( \overline{u'^{2}} \)                               |`u2`| \( \overline{u} \)                          |
|9| \( \overline{v'^{2}} \)                               |`v2`| \( \overline{v} \)                          |
|10|\( \overline{w'^{2}} \)                               |`w2`| \( \overline{w} \)                          |
|11|\( \overline{p'^{2}} \)                               |`p2`| \( \overline{p} \)                          |
|12|\( k \)                                               |`km`| \( \overline{u},\overline{v},\overline{w}\) |
|13|\(\overline{\boldsymbol{\nabla}\cdot\boldsymbol{u}} \)|`dm`| -                                           |

**Table**: list of currently available statistics along with their ID and other statistics dependency.


As for other parts of the program, `postproc` has a dedicated `POSTPROC` section in `settings.in`, where its output can be configured.
Currently, one can set the `vtkFileType` to  `r` (rectilinear) or `u` (unstructured), and choose whether to convert to VTK the binary files with statistics, and/or the binary files of the entire snapshots database.

| **Name** | **Values** | **Description** |
|----------|------------|------------------|
|**`generateStatsVtk`**  | `YES`/`NO` |Whether statistics are converted in VTK |
|**`generateFieldVtk`**  | `YES`/`NO` |Whether snapshots  are converted in VTK |
|**`generateAveragedStatsDat`**|`YES`/`NO` |Whether ASCII files with statistics averaged in homogeneous directions are created|
|**`statsVtkFileType`**|`r`/`u`| Sets the type of statistics VTK file to rectilinear (`r`) <br> or unstructured (`u`) |
|**`fieldVtkFileType`**|`r`/`u`| Sets the type of snaptshots VTK file to rectilinear (`r`)<br> or unstructured (`u`)|
|**`homogeneousDirs`**|`0/1 0/1 0/1`| Sets each direction to non-homogeneous/homogeneous |

**Table**: the `POSTPROC` section of `settings.in`

### Statistics 

When `generateStatsVtk=YES`, `postproc` reads the content of `statsNames` and verifies the match with the binary statistics actually saved by `solver` (an error is triggered if this is not the case). 

When `generateAveragedStatsDat=YES`, `postproc` also averages statistics in homogeneous directions, and produces an ASCII output. 
`postproc` accepts any combination of homogeneous/non-homogeneous directions, except `homogeneousDirs= 1 1 1` (currently returns an error in this case, work in progress). When `homogeneousDirs= 0 0 0`, no ASCII file is produced.

When the homogeneous directions are two (as for the channel flow example, where `homogeneousDirs= 1 0 1`), a tab-separated `averStats.dat` file is generated in the `stats/` folder, with the name of the included statistics on its first line. 
When only one homogeneous direction is present, the statistics are two-dimensional: each quantity is saved to a different `.dat` file, named as `averaged_<statID>.dat` where `<statID>` is once again the corresponding statistics ID. The coordinate of the first/second non-homogeneous direction spans the lines/columns of the file.

### Flow field database

The snapshots saved by `solver` are stored in `database/binary`, and are organized in [subfolders](overview.md#folder-structure), one for each snapshot. Each folder is named as `count-000<iSnap>`, and contains all the subdomain files for the snapshot `iSnap`. 
When `generateFieldVtk=YES`, `postproc` converts the snapshots to VTK, replicating the folder structure in `database/vtk`. 
Since this folder structure does not allow popular visualization tools like Paraview to recognize that each folder contains multiple subdomains at one time, `postproc` also generates a `.vtk.series` JSON file for each subdomain. The series files are stored in `database/vtk/series`; each allows to load all the snapshots of one subdomain. Series files can be merged through `Merge Datasets` in Paraview for the visualization of the whole domain.
Loading `.series` files requires [Paraview version 5.5.0](https://gitlab.kitware.com/paraview/paraview/blob/v5.5.0/Documentation/release/ParaView-5.5.0.md#json-based-new-meta-file-format-for-series-added) or later.

