Voxel Variables¶
Introduction¶
Most voxel variables in M-Star CFD are computed using user-defined functions (UDFs), which provide the flexibility to define custom physics, perform localized reductions, and embed advanced calculations directly into the simulation. Voxel variables are quantities defined at each individual lattice site within the computational domain. Every voxel in the lattice maintains its own independent value, affixed directly to the grid point. These variables do not advect, diffuse, or propagate like scatter fields; instead, they represent localized calculations or reductions performed specifically at each voxel location, using nearby fluid and/or particle properties as inputs to the UDF.
Download Sample File: Voxel Variables Lambda 2
In the example above, we compute the local λ₂ field from the velocity gradient tensor. The λ₂ criterion (Jeong & Hussain, 1995) identifies vortical regions as those where the second largest eigenvalue of \(S^2 + \Omega^2\) is negative. M-Star calculates this quantity at every grid point, producing a scalar field that can be visualized as isosurfaces (e.g., λ₂ < 0) to highlight coherent vortex structures. This example computes both the instantaneous λ₂ field and its time average over the simulation. The instantaneous field applies the classical λ₂ criterion for vortex identification. The time-averaged λ₂ field does not represent a strict vortex identification test, but provides a statistical measure of where vortical regions persist over time.
When defined from fluid properties, voxel variables make use of locally available continuous quantities, such as velocity, strain rate, species concentrations, temperature, turbulent energy dissipation rate (EDR), or local volume fraction. A voxel variable may, for example, compute the shear rate at each lattice site or evaluate a custom viscosity expression that depends simultaneously on temperature and concentration.
When based on particle properties, voxel variables treat each voxel as a small control volume and perform reductions over the particles contained within its extents. In this case, the UDF operates on particle-level quantities, and a reduction type must be specified to condense multiple particle values into a single scalar or vector at that voxel. Examples include summing particle volumes to compute total particle volume fraction, averaging particle diameters, or calculating the local maximum particle velocity. By collapsing all particle data within a voxel into a single representative value, voxel variables allow localized particle statistics to be used seamlessly alongside fluid-based quantities within the same framework.
Voxel variables can be defined as either scalar or vector-valued and can be computed in two primary ways. Firstly, and in most cases, they are calculated instantaneously via local UDFs that operate directly on current fluid and particle properties at runtime. Secondly, voxel variables can represent time-averaged quantities, where values from another custom variable are accumulated and averaged over a user-specified window.
Importantly, voxel variables are not limited to visualization or reporting. Because they are fully integrated into the solver, they can be referenced throughout the code as intermediate inputs to other calculations—such as custom viscosity models, complex reaction kinetics, or transport closures—or used directly as final outputs for downstream analysis and validation. By combining flexible UDF-driven definitions with seamless integration into the simulation framework, voxel variables enable highly customized, localized descriptions of flow behavior and particle statistics across the lattice.
Property Grid¶
General
¶
- Template
This setting specifies the starting configuration for the variable.
- Custom
This evaluates a user-defined expression via a UDF. These expressions can reference local fluid properties, local particle data, other custom variables, global constants, and UDF regions, allowing you to define highly customized quantities.
- Time Average Uniform
This performs a uniform time average of another variable over a specified averaging window, giving equal weight to all timesteps within the window.
- Time Average Exponential
This performs an exponentially weighted time average of another variable, placing greater emphasis on more recent data.
- Data Type
The Data Type setting determines whether the variable represents a scalar or a vector quantity. For Custom variables, this choice must be explicitly specified.
- Scalar
This computes a single-valued output at each voxel, particle, or surface location. The calculation UDF must return a single value to represent this output.
- Vector
This computes a three-component directional output at each lattice site, particle, or surface. In this case, the calculation UDF must define all three components of the vector explicitly.
For Time-Averaged variables, the data type is inherited automatically from the input variable being averaged. If the input variable is scalar, the averaged result will be scalar; if the input is vector-valued, the averaged result will also be vector-valued.
- Input Data
This setting determines what type of data is used when computing the voxel variable. It does not change where the variable is stored (it is always defined per voxel); but this setting controls which underlying data sources are evaluated by the user-defined function.
- Fluid
This calculation uses continuous local field data from the lattice. This can include any combination of fluid properties, temperature fields, scatter field variables, or other continuous quantities defined on the grid. The UDF operates directly on these values to compute the voxel variable at each lattice site.
- Particles
This calculation uses particle-based data instead of continuous fluid properties. In this case, each voxel is treated as a small control volume: the set of particles contained within the voxel’s extents is gathered, and a reduction is performed over that population to collapse particle-level information into a single scalar or vector value for the voxel. For example, you might compute the total particle volume fraction, the mean particle velocity, or the maximum particle diameter within each voxel.
When Particles is selected as the Input Data, you must also specify the associated particle set and reduction type.
- Particle Set
This parameter defines the specific particle family included in the reduction.
- Reduction Type
When using particle data to compute voxel variables, multiple particles may occupy the same voxel, and a single value must be derived to represent that voxel. The Reduction Type specifies how the custom variable computed for each particle is aggregated into a single scalar or vector value. Four reduction types are available:
- Min
This reports the minimum UDF value across all particles inside the voxel.
- Max
This reports the maximum UDF value across all particles inside the voxel.
- Sum
This reports the sum of all UDF values across all particles inside the voxel.
- Mean
This reports the mean of all UDF values across all particle inside the voxel.
- Initial Value
This parameter defines the starting value assigned to the variable before any runtime calculations begin. For most custom variables, this is typically left at zero, but it can be set to a different baseline where appropriate.
If the Data Type is set to Scalar, a single initial value is specified. However, if the Data Type is set to Vector, three initial components of the vector are specified. These values establish the initial state of each component prior to the UDF-driven calculations.
- Voxel Variable UDF
depends on UDF expression | This UDF defines the custom property to be calculated in each voxel. If the Data Type is set to scalar, one output must be defined within the UDF: a floating-point variable named
{cv}
, where{cv}
is the dynamic name of the custom voxel variable. If the Data Type is set to vector, the components of the vector must be defined individually as{cv}_x
,{cv}_y
and{cv}_z
. This variable can be used in other local UDFs. This is a voxel-based local UDF, calculated on a voxel-by-voxel basis using the local UDF properties.Download Sample File:
Voxel Variables Particles
In this example file, we inject solid particles into a horizontal pipe with a static mixer. Because of the particle-size distribution (PSD), the cross-sectional concentration becomes non-uniform. Using a Voxel Variable with particles as the Input Variable, we compute the average particle diameter within each voxel. As expected, particles preferentially concentrate near the bottom of the pipe due to gravity-induced settling.
This calculation defines how the custom variable is computed during the simulation. In most cases, this is done using a User-Defined Function (UDF). A UDF is a user-supplied code snippet written in C-style syntax that allows you to define custom calculations based on local fluid properties, particle properties, or other custom variables.
For custom variables, the Voxel Variable UDF is evaluated on a voxel-by-voxel basis, meaning the calculation is performed independently at each lattice site using the local values available there. Depending on the Input Data, the UDF may operate on:
Scalar Fields: Where the UDF produces a single floating-point output for each voxel.
Vector Fields: Where the UDF must explicitly return three separate outputs, one for each directional component (x, y, and z). These are defined individually within the UDF and collectively represent the vector-valued result at each lattice site.
Particle-based Reductions: Where the UDF computes a property for each particle, and a reduction type (e.g., sum, mean, min, or max) condenses these particle-level results into a single scalar or vector value per voxel.
The UDF must define exactly one output variable for scalars or three output variables for vectors. These outputs are assigned to a floating-point variable (or variables) named {cv}, where {cv} is the dynamic name of the custom variable being defined. Once computed, these variables can be referenced by other local UDFs, used as inputs to time-averaged variables, or integrated into expressions elsewhere in the code, such as viscosity models or reaction kinetics.
For time-averaged variables—whether TimeAverageUniform or TimeAverageExponential—this field does not appear, since there is no explicit calculation performed here. Instead, the variable simply averages the values of another input scalar or vector field over time. In many cases, the input field itself is a custom variable computed via a UDF, but the averaging step requires no additional user-defined code.
Advanced
¶
The Advanced settings provide additional controls over how custom variables are displayed, reported, and integrated into the simulation framework.
- Compute Frequency
This setting controls whether the variable is available exclusively for reporting and post-processing or whether it can also be referenced elsewhere in the simulation as an intermediate variable.
- Output Only
The variable is computed but is restricted to output purposes only. It can be used for visualization and exported results but cannot be referenced by other user-defined functions, expressions, or solver routines.
- Every Time Step
The variable becomes fully integrated into the solver and can be used as an input to other calculations. For example, a voxel variable could feed directly into custom viscosity models, reaction kinetics expressions, transport closures, or additional derived variables defined elsewhere in the code.
- Display Name Override
This setting controls how the variable name appears in the GUI and exported results. These overrides do not affect the internal computation but allow you to customize presentation for clarity during downstream analysis.
- Display Unit Override
This setting controls how the variable units appears in the GUI and exported results. These overrides do not affect the internal computation but allow you to customize presentation for clarity during downstream analysis.
If the fluid type is set to Free Surface, the following option will launch:
Free Surface Clipping
¶
This setting controls whether the variable is evaluated and printed above the free surface in simulations where a liquid–air interface is present. It can be toggled On or Off depending on whether contributions from the gas phase are relevant.
- Enabled (On)
The variable is computed only at output intervals when data is written to files or visualizations. Because the solver skips calculating the variable at every time step, this mode can make the simulation more efficient, especially when working with computationally expensive UDFs or large particle sets. However, the variable cannot be referenced by other UDFs, expressions, or solver-driven calculations since it isn’t continuously available.
- Disabled (Off)
The variable is evaluated and printed everywhere, including both the liquid and gas phases. This is useful when defining variables that must account for the entire computational domain or when analyzing properties that may extend across phase boundaries.
Voxel Variable Toolbar¶
Context-Specific Toolbar Forms |
Description |
---|---|
|
The Help command launches the M-Star reference documentation in your web browser. |
For a full description of each selection on the Context-Specific Toolbar, see Toolbar Selections.