# Freestream Boundary Condition

*The Freestream boundary condition represents the far-field conditions in external aerodynamics simulations, defining the flow conditions at the external boundaries of the computational domain.*

---

## Available Options

| *Option* | *Description* | *Applicable* |
|------------|----------------------------------|----------|
| **Use operating condition's velocity** | The velocity specified at the boundary condition is the same as in [Operating condition](../../01.flow-conditions/README.md) | always |
| **Custom** | Option to use local settings rather than those from Operating Condition | always |
| **Velocity Components** | Components of velocity vector (constants or expressions) | **Custom** is selected |
| **Turbulence Quantities** | Specification of turbulence parameters | always | 
| **Assigned surfaces** | Geometric boundaries to apply the freestream condition | always |

---

## Detailed Descriptions

### Use operating condition's velocity

*Uses freestream conditions defined in the [Operating condition](../../01.flow-conditions/README.md) section.*

- **Default:** Selected

### Custom

*Allows specification of local freestream conditions for this boundary instead of using the freestream conditions defined in the Operating Condition section.*

- **Default:** Unselected

### Velocity Components

*Explicit values or expressions for the freestream velocity vector, available when overriding Operating Condition settings.*

- **Required when `Custom` is selected**
- **Example (constants):** `(100, 0, 0) m/s`
- **Example (expression):** `[100, 0, 0] * u.m / u.s`
>**Notes:** 
>- When specified, these values override the velocity derived from velocity or Mach number, alpha, and beta angles in the Operating Condition section
>- A selector at the top of the field switches between `Constant` and `Expression`. `Expression` takes a single expression for the whole vector, built from units, `math` functions and [custom variables](../../../05.tools/02.variable-settings.md)
>- The expression is evaluated when the case is submitted, so it cannot depend on `control` or `solution` variables. A velocity that varies in space or time is available only through the Python API, as a C-style expression per component (for example `X="min(1.0, 0.1*t)"`)
>- Per-component C-style expressions carry no units. Their result is read in solver units, nondimensionalized by the [reference velocity scaling $U_{scale}$](../../04.output/scaling-values.md#reference-velocity-scaling), and the coordinates `x`, `y`, `z` and the time `t` used inside them are nondimensional as well

### Turbulence Quantities

*Optional specification of turbulence parameters at the boundary.*

- **Options:** Various parameter combinations
- **Default:** Uses defaults based on turbulence model defined in Operating Condition
- **Example:** `Turbulence Intensity = 0.01`, `Turbulent Length Scale = 0.1 m`
>**Notes:** 
>- Only specify at most two turbulence parameters
>- See [Turbulence Quantities documentation](./09.turbulence-quantities.md) for valid combinations and detailed explanations
  
### Assigned surfaces

*Specifies the geometric boundaries to which the freestream boundary condition is applied.*

- **Accepted types:** Surface
>**Notes:** 
>- Assign the boundaries by selecting from the list using the + button or select graphically in the viewer region. 
>- Compatible with the `AutomatedFarfield` feature that creates appropriate far-field boundaries.

---

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

**Domain Size Considerations**

- Place freestream boundaries 50-100 characteristic lengths away from the object of interest
- For subsonic flows, ensure boundaries are far enough to avoid artificial acceleration effects
- For supersonic flows, place the inlet boundary at least 3-5 characteristic lengths upstream

**Automated Farfield Creation**

- Flow360 provides an `AutomatedFarfield` feature that generates appropriate far-field boundaries
- These automated boundaries can be used with the Freestream condition for simplified setup
- Particularly useful for external aerodynamics simulations

**Turbulence Specification Guidelines**

- For external aerodynamics:
  - Use lower turbulence intensity (0.1-1%)
  - Set turbulent length scale proportional to characteristic length (1-10%)
- For specific atmospheric conditions:
  - Calm air: Turbulence intensity ~0.1%
  - Moderate atmospheric turbulence: 1-5%
  - High atmospheric turbulence: 5-10%

</details>

---

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

- **How far should I place the freestream boundary from my geometry?**  
  > For subsonic flows, place boundaries at least 50-100 characteristic lengths away. For supersonic flows, the outlet can be closer (10-20 lengths), but the inlet should still be at least 3-5 lengths upstream to allow proper bow shock formation.

- **When should I specify explicit turbulence quantities?**  
  > Specify turbulence quantities when you need to match specific experimental conditions or when modeling environments with known turbulence levels, such as wind tunnel tests or atmospheric flight conditions.

- **Can I use varying freestream conditions at different boundaries?**  
  > Yes, by overriding the Operating Condition settings and specifying local velocity components for each freestream boundary. This is useful for modeling non-uniform approach flows.

- **Can I use expressions for velocity components?**  
  > Yes, but only through the Python API (not available in the GUI). In the Python API, each velocity component can be specified as a C-style string expression using variables like x, y, z, and t. This allows for spatially or temporally varying freestream conditions in programmatically created simulations. Such an expression carries no units — everything in it, input and result alike, is nondimensional. A component of `1.0` is one $U_{scale}$, which for an `AerospaceCondition` is the freestream speed of sound, i.e. Mach 1. Divide your dimensional target by $U_{scale}$ before writing it into the string.

- **How do the turbulence settings affect my results?**  
  > Turbulence settings at freestream boundaries influence the development of boundary layers and can affect transition location. Higher turbulence intensities typically promote earlier transition from laminar to turbulent flow.

</details>

---

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

```{seealso}
Python API:

- {py:class}`~flow360.Freestream`
- {py:class}`~flow360.TurbulenceQuantities`
- {py:class}`~flow360.AutomatedFarfield`
```

```python
# Example using operating condition settings (default velocity)
freestream_bc = fl.Freestream(
    name="farfield",
    entities=volume_mesh["farfield"]
)

# Example with explicit velocity components as a list
freestream_with_velocity = fl.Freestream(
    name="farfield_custom",
    entities=volume_mesh["farfield"],
    velocity=[100 , 10, 0 ] * fl.u.m / fl.u.s
)

# Example with velocity expressions
freestream_with_expressions = fl.Freestream(
    name="farfield_varying",
    entities=[volume_mesh["blk-1/freestream-part1"], 
              volume_mesh["blk-1/freestream-part2"]],
    # C-style string components are nondimensional multiples of U_scale, NOT m/s:
    # "min(0.3, 0.3*t/10)" ramps up to 0.3 * U_scale (Mach 0.3 for an AerospaceCondition)
    velocity=["min(0.3, 0.3*t/10)", "0.03*sin(t)", "0"]
)

# Example with turbulence specifications for k-ω SST model
freestream_with_turbulence = fl.Freestream(
    name="farfield_turbulent",
    entities=volume_mesh["farfield"],
    turbulence_quantities=fl.TurbulenceQuantities(
        turbulent_intensity=0.01,  # 1% turbulence intensity
        turbulent_length_scale=0.1 * fl.u.m
    )
)

# Example with automated farfield
auto_farfield = fl.AutomatedFarfield()
freestream_auto = fl.Freestream(
    name="auto_farfield",
    entities=[auto_farfield.farfield],
    turbulence_quantities=fl.TurbulenceQuantities(
        modified_viscosity_ratio=10
    )
)

# Example for Spalart-Allmaras model
freestream_sa = fl.Freestream(
    name="farfield_sa",
    entities=volume_mesh["farfield"],
    turbulence_quantities=fl.TurbulenceQuantities(
        viscosity_ratio=5.0  # Ratio of turbulent to laminar viscosity
    )
)
```

</details>
