# Isosurface Output

*Isosurface Output in Flow360 lets you visualize flow field variables on surfaces of constant value within the computational domain. This is particularly useful for identifying and analyzing coherent structures like vortices, shock waves, or temperature contours.*

---

## Available Options

| *Option* | *Description* | *Applicable* |
|----------|---------------|--------------|
| **Output fields** | Flow variables to include in the output | always |
| **Output format** | Format for saving isosurface data | always |
| **Save interval** | When to save outputs | always |
| **Frequency** | How often to save outputs | when **Save interval** is `Custom` |
| **Frequency offset** | Time step at which to start the output animation | when **Save interval** is `Custom` |
| **Isosurfaces** | Define one or more isosurfaces | always |

```{seealso}
For the underlying physics and configuration of outputs, see the {doc}`/user_guide/OutputConfiguration/OutputConfiguration` user guide.
```

---

## Global Time Stepping in Child Cases

When working with **child cases** (cases forked from a parent simulation), it's important to understand that the `Frequency` and `Frequency offset` parameters refer to the **global** time step, which is transferred from the parent case.

**Example:** If the parent case finished at `time_step=174`, the child case will start from `time_step=175`. If `Frequency=100` is set in the child case, the output will be saved at global time steps 200 (25 time steps into the child simulation), 300 (125 time steps into the child simulation), etc. `Frequency offset` also refers to the global time step, meaning that if in the previously mentioned child case, `Frequency offset=50` was set (with `Frequency=100`), the output would be saved at **global** time steps 250 (75 time steps into the child simulation), 350 (175 time steps into the child simulation), etc.

---

## Detailed Descriptions

### Output fields

*Select the flow variables to include in the isosurface output.*

- **Default:** None
- **Example:** `Mach, pressure, velocity`
>**Notes:** isosurface outputs support all [Universal Fields](../output-fields.md#universal-fields). See the [Available Output Fields](../output-fields.md) page for a complete reference, including commonly used fields for isosurface visualization.

### Output format

*The file format used to save the isosurface output data.*

- **Default:** `paraview`
- **Example:** `["paraview", "tecplot"]`
- **Options:** (multi-select; choose one or more)
  - `paraview`
  - `tecplot`
  - `vtkhdf`
  - `ensight`
> **Notes:** 
> - Choose the format that best suits your post-processing workflow.
> - The **Output format** control is multi-select: pick one or more of `paraview`, `tecplot`, `vtkhdf`, or `ensight`. See [Output Formats](19.output-formats.md) for file extensions and details.

### Save interval

*Choose the points in the simulation where the results are saved.*

- **Default:** `Save at end`
- **Options:**
  - `Save at end`
  - `Custom` (only available when `Time stepping` is `Unsteady`)
> **Notes:** 
> - Choose `Save at end` to save only the final results of the simulation.
> - Choose `Custom` to save the results in given intervals.
> - `Custom` cannot be selected when `Time stepping` is `Steady`. A save frequency counted in pseudo steps can still be set for this output through the Python API, see {ref}`Output Save Frequency <outputFrequency_userGuide>`.

### Frequency

*How often to save outputs, in number of physical time steps.*

- **Default:** `-1` (only at the end of simulation)
- **Example:** `100` — saves output every 100 physical time steps.
  - **Standalone case:** If you start a simulation from `time_step=0` with `frequency=100`, outputs are saved at time steps 100, 200, 300, etc.
  - **Parent-child case:** If the parent finished at `time_step=174`, the child starts from `time_step=175`. With `frequency=100` in the child, outputs are saved at global time steps 200 (25 steps into child), 300 (125 steps into child), 400 (225 steps into child), etc.
>**Notes:** 
> - Higher frequencies provide better temporal resolution but increase storage requirements.
> - Important for child cases - this parameter refers to the **global** time step (see [Global Time Stepping](#global-time-stepping-in-child-cases)).
> - This setting is only applicable for unsteady cases.

### Frequency offset

*The time step at which to start the output animation.*

- **Default:** `0` (beginning of simulation)
- **Example:** `1000` — with `frequency=100`, outputs are saved at time steps 1000, 1100, 1200, etc.
  - **Standalone case:** If you start a simulation from `time_step=0` with `frequency=100` and `frequency_offset=1000`, outputs are saved at time steps 1000, 1100, 1200, etc.
  - **Parent-child case:** If the parent finished at `time_step=174`, the child starts from `time_step=175`. With `frequency=100` and `frequency_offset=200` in the child, outputs are saved at global time steps 200 (25 steps into child), 300 (125 steps into child), 400 (225 steps into child), etc.
>**Notes:** 
> - Useful when you want to skip initial transient flow development.
> - Important for child cases - this parameter refers to the **global** time step (see [Global Time Stepping](#global-time-stepping-in-child-cases)).
> - This setting is only applicable for unsteady cases.

### Assigned isosurfaces

*Define one or more isosurfaces by specifying a field variable and iso-value.*

- **Default:** None
- **Definition parameters:**
  - **Name:** A unique identifier for the isosurface
  - **Field:** The flow variable used to define the isosurface
  - **Iso-value:** The constant value of the field variable that defines the isosurface
  - **Clipping box:** Optional. Limits this isosurface to the region inside a single selected **Box** entity, leaving it spanning the whole domain if unset
- **Example:** `qcriterion = 0.001`

```{seealso}
{ref}`Limiting the Extent of an Isosurface <isosurfaceExtent_userGuide>` in the user guide, which covers how the box is applied and a second limit, based on distance from walls, that is available only through the Python API.
```

---

## Available Isosurface Fields

*Isosurfaces can be defined based on the following field variables:*

- `p` - Pressure (non-dimensional)
- `rho` - Density (non-dimensional)
- `Mach` - Mach number (non-dimensional)
- `qcriterion` - Q criterion (for vortex identification) (non-dimensional)
- `s` - Entropy (non-dimensional)
- `T` - Temperature (non-dimensional)
- `Cp` - Coefficient of pressure (non-dimensional)
- `Cpt` - Total pressure coefficient (non-dimensional)
- `mut` - Turbulent viscosity (non-dimensional)
- `nuHat` - Spalart-Almaras variable (non-dimensional)
- `vorticityMagnitude` - Vorticity Magnitude (non-dimensional)

---

<details>
<summary><h3 style="display:inline-block"> 💡 Tips</h3></summary>

**Choosing a field and iso-value for a given flow feature**

- To visualize **vortices**, create an isosurface of `qcriterion` at a small positive value. A good starting point is `Mach² / WingSpan²` for aircraft or `TipMach² / RotorDiameter²` for rotor flows (the auto-generated default is `RefMach² / (all walls' bounding box length)²`). Use smaller values to reveal more vortical structures, larger values to isolate only the strongest vortices.
- To visualize **shock waves**, create an isosurface of `Mach` around `1.0` (for transonic flows), or of a density/pressure gradient for a cleaner shock front.
- To visualize **thermal features**, create an isosurface of `T` (temperature); use several iso-values to show temperature stratification.
- To visualize **separation and recirculation regions**, create an isosurface of velocity (or skin friction) near zero.

</details>

---

<details>
<summary><h3 style="display:inline-block"> ❓ Frequently Asked Questions</h3></summary>

- **How do I choose the right iso-value for Q-criterion visualization?**  
  > Start with a value based on the flow characteristics:
  > - For aircraft: Try `Mach² / WingSpan²`
  > - For rotors: Try `TipMach² / RotorDiameter²`
  > - Decrease the value if you want to see more vortical structures
  > - Increase the value if you want to focus only on strongest vortices
  > - Experiment with different values, starting with orders of magnitude (0.1, 0.01, 0.001)

- **Can I create multiple isosurfaces with different fields in a single output?**  
  > Yes! You can define multiple isosurfaces in a single isosurface output:
  > - Each with different fields (e.g., one for `qcriterion`, one for `Mach`)
  > - Each with different iso-values
  > - All sharing the same output fields and frequency settings
  > This approach is more efficient than creating multiple separate isosurface outputs.

- **Why are my isosurfaces flickering in animations?**  
  > Isosurface flickering can occur due to:
  > - Unsteady flows where structures evolve rapidly
  > - Iso-values too close to background noise levels
  > - Insufficient temporal resolution (increase output frequency)
  > - Consider time-averaging for statistical visualization of unsteady features

- **How large are isosurface output files typically?**  
  > File sizes for isosurfaces are generally much smaller than volume outputs:
  > - Size depends on the complexity of the isosurface (how many triangles are needed to represent it)
  > - More complex flow features and lower iso-values typically generate larger files
  > - Each output field adds data to every point on the isosurface
  > - For a typical simulation, isosurface files might be 10-100 MB per timestep (compared to GB for volume outputs)

- **Why is my isosurface broken or incomplete?**  
  > Broken isosurfaces might occur because:
  > - The iso-value is too high, breaking continuous structures
  > - The feature doesn't exist in parts of the domain
  > - Flow features are evolving (especially in unsteady simulations)
  > - Output frequency may be too low to capture continuous evolution

</details>

---

<details>
<summary><h3 style="display:inline-block"> 🐍 Python Example Usage</h3></summary>

```{seealso}
Python API reference: {py:class}`~flow360.IsosurfaceOutput`, {py:class}`~flow360.Isosurface`.
```

```python
# Example of configuring isosurface output using Flow360 Python API
import flow360 as fl
from flow360 import u

# Define multiple isosurfaces with different fields and values
isosurface_output = fl.IsosurfaceOutput(
    name="Flow Structures",
    output_format=["paraview"],
    isosurfaces=[
        fl.Isosurface(
            name="Vortex_Cores",
            iso_value=0.001,
            field="qcriterion",
        ),
        fl.Isosurface(
            name="Shock_Wave",
            iso_value=1.0,
            field="Mach",
        ),
        fl.Isosurface(
            name="Hot_Region",
            iso_value=1.2,
            field="T",
        ),
    ],
    output_fields=["velocity", "pressure", "Mach"],
    frequency=100,  # Save every 100 time steps
    frequency_offset=0,  # Start at the beginning of simulation
)

# Add isosurface output to simulation parameters
simulation_params = fl.SimulationParams(
    # ... other simulation parameters ...
    outputs=[isosurface_output]
)
```

</details> 