SRF with Cube#
This notebook demonstrates how to set up a Single Rotating Frame (SRF) simulation with a mesh of a simple cube using snappyHexMesh in Flow360.
Key features demonstrated:
Integration of snappyHexMesh for surface meshing with Flow360’s new volume mesher
Definition of rotating zones using the
RotationmodelSetup of boundary conditions for SRF simulations
Use of the modular meshing workflow with custom zones

Note: The settings in this example are by no means a validation setup; they are crafted to showcase the capabilities of Flow360 and we have intentionally reduced node count and example FC cost. For rigorous validation, modify the settings as needed.
1. Create Project from geometry#
The first step is to initialize the Flow360 client and create a project from the geometry file.
Key steps:
Load libraries: Import
flow360and the example geometry (Cube). TheCubeexample provides a pre-configured STL file for demonstration purposes — it contains two named solids,cubeandfarfield.Create project: Use
fl.Project.from_geometry()to create a project from the CAD file. Specify thelength_unit(meters in this case).Group bodies and faces: From release 25.10 onward, snappy uses the same conventional grouping mechanism as the other surface meshers. Call
geo.group_bodies_by_tag("groupByFile")to expose each input STL file as a body group (here, a singlecube.stlbody), andgeo.group_faces_by_tag("faceId")to expose each named STL solid as an addressable surface (here,geo["cube"]andgeo["farfield"]).
[ ]:
import flow360 as fl
from flow360.examples import Cube
fl.Env.preprod.active()
Cube.get_files()
project = fl.Project.from_geometry(
Cube.geometry, name="SRF Cube", length_unit="m"
)
geo = project.geometry
geo.show_available_groupings(verbose_mode=True)
geo.group_bodies_by_tag("groupByFile")
geo.group_faces_by_tag("faceId")
[06:05:30] INFO: The file (cube.stl) is being downloaded, please wait.
[06:05:48] INFO: Geometry successfully submitted: type = Geometry name = SRF Cube id = geo-8810a17f-5c89-4203-b66d-2f6973408725 status = uploaded project id = prj-fee2c42f-311f-4e60-8c4f-90f8512d066b
INFO: Waiting for geometry to be processed.
[06:06:11] INFO: >> Available attribute tags for grouping **faces**:
INFO: >> Tag '0': groupByBodyId. Grouping with this tag results in:
INFO: >> [0]: cube.stl
INFO: IDs: ['cube', 'farfield']
INFO: >> Available attribute tags for grouping **edges**:
INFO: >> Available attribute tags for grouping **bodies**:
INFO: >> Tag '1': groupByFile. Grouping with this tag results in:
INFO: >> [0]: cube.stl
INFO: IDs: ['cube.stl']
2. Meshing Parameters#
The meshing configuration uses Flow360’s modular meshing workflow, which allows you to independently choose surface and volume meshers. This example combines:
Surface meshing: snappyHexMesh integration via
fl.snappy.SurfaceMeshingParamsVolume meshing: Flow360’s new volume mesher via
fl.VolumeMeshingParams
Defining the fluid zone:
The fluid domain must be explicitly defined using a SeedpointVolume:
point_in_mesh: A list of one or more coordinate points that lie inside the fluid region (e.g.,[[10.1435, 0, 0]]). The seed points help the mesher identify which volume is the fluid domain.centerandaxis: Define the center and rotation axis for the volume. These are critical for SRF simulations, as they specify the rotation reference frame. Here,center=(0, 0, 0)andaxis=(1, 0, 0)indicate rotation about the x-axis through the origin.Convert to zone: Wrap the
SeedpointVolumein aCustomZonesobject to make it available for meshing and physics models.
Surface meshing configuration:
``SurfaceMeshingDefaults``: Global surface meshing parameters:
min_spacingandmax_spacing: Control the surface mesh resolutiongap_resolution: Minimum feature size to capture (1 mm)
``RegionRefinement``: Refine a specific surface (region) of the geometry. Here it targets
geo["cube"]— the cube face exposed by thefaceIdgrouping — to give the wall a finer mesh than the surrounding farfield. Faces are addressed by their STL solid name (geo["<face>"]); bodies are addressed by their file name (geo["<file>.stl"]) and accepted byfl.snappy.BodyRefinementwhen the refinement should cover the whole body.``SurfaceEdgeRefinement``: Refine the mesh along surface edges to capture sharp features and geometric discontinuities. If this refinement is not used, the edges are not guaranteed to be kept by snappyHexMesh. The
spacingparameter (50 mm in this example) controls the mesh size along edges, whiledistances(2 mm) defines the distance from the edge where this refinement is applied.
Volume meshing configuration:
``VolumeMeshingDefaults``: Set boundary layer parameters:
boundary_layer_first_layer_thickness: Thickness of the first boundary layer cell (1 mm), which affects near-wall resolution and is important for accurate wall-bounded flow predictions.
Volume meshing refinements:
``PassiveSpacing``: Preserve the surface mesh spacing on specified faces. Applied to the farfield surface
geo["farfield"]withtype='unchanged', this prevents the volume mesher from modifying the mesh spacing on the farfield boundary, maintaining the resolution determined by the surface mesher.``UniformRefinement``: Apply uniform mesh spacing within a defined region. Here, a box region (center at (0.5, 0, 0) with size 3×2×2 m) is refined to 50 mm spacing to ensure adequate resolution around the cube geometry in the near-field region.
Important: When using the new volume mesher, you must set use_beta_mesher=True when running the case (see Section 5).
[2]:
with fl.SI_unit_system:
fluid = fl.SeedpointVolume(name="fluid", point_in_mesh=[(10.1435, 0, 0)], center=(0, 0, 0), axis=(1, 0, 0))
fluid_zone = fl.CustomZones(name="fluid", entities=[fluid])
meshing_params = fl.ModularMeshingWorkflow(
surface_meshing=fl.snappy.SurfaceMeshingParams(
defaults=fl.snappy.SurfaceMeshingDefaults(
min_spacing=0.5 * fl.u.m, max_spacing=2 * fl.u.m, gap_resolution=1 * fl.u.mm
),
refinements=[
fl.snappy.RegionRefinement(
min_spacing=50 * fl.u.mm, max_spacing=100 * fl.u.mm,
regions=[geo["cube"]]
),
fl.snappy.SurfaceEdgeRefinement(
spacing=[50 * fl.u.mm],
distances=[2 * fl.u.mm],
entities=[geo["cube"]]
)
]
),
volume_meshing=fl.VolumeMeshingParams(
defaults=fl.VolumeMeshingDefaults(boundary_layer_first_layer_thickness=1 * fl.u.mm),
refinements=[
fl.PassiveSpacing(
faces=[geo["farfield"]],
type='unchanged'
),
fl.UniformRefinement(
entities=fl.Box(name="box", center=(0.5, 0, 0), size=(3, 2, 2)),
spacing=50 * fl.u.mm
)
]
),
zones=[fluid_zone],
)
INFO: using: SI unit system for unit inference.
3. Create Rotating Model#
In an SRF simulation, the entire computational domain rotates as a rigid body. The Rotation model defines which volumes rotate and at what angular velocity.
Key parameters:
``name``: A descriptive name for the rotation model (e.g.,
"rotating_farfield")``volumes``: List of volumes that rotate. Here, we use the
fluidvolume defined earlier, which means the entire fluid domain rotates.``spec``: The rotation specification.
AngularVelocity(10 * fl.u.rpm)sets the domain to rotate at 10 revolutions per minute about the axis defined in theSeedpointVolume(x-axis through the origin).
Important considerations:
The rotation axis and center must match those defined in the
SeedpointVolume(Section 2) for consistency.In SRF simulations, boundary conditions are applied in the rotating frame. For example, a freestream velocity is specified relative to the rotating domain.
The
Rotationmodel is added to themodelslist inSimulationParams(Section 4), not as a boundary condition.
[3]:
with fl.SI_unit_system:
rotating_farfield = fl.Rotation(
name="rotating_fluid",
volumes=[fluid],
spec=fl.AngularVelocity(50 * fl.u.rpm)
)
INFO: using: SI unit system for unit inference.
4. Create SimulationParams#
The SimulationParams class consolidates all simulation settings: meshing, physics, boundary conditions, and solver options.
Configuration components:
``meshing``: Reference to the
ModularMeshingWorkflowdefined in Section 2.``operating_condition``: Defines the flow conditions:
AerospaceCondition(velocity_magnitude=10 * fl.u.m / fl.u.s): Sets a freestream velocity of 10 m/s. In SRF simulations, this velocity is relative to the rotating frame.
``time_stepping``:
Steady()indicates a steady-state simulation. For unsteady SRF cases, useUnsteady()with appropriate time step settings.``models``: List of physics models and boundary conditions:
``Wall``: Applied to the cube surface using
geo["cube"]. Each STL solid is exposed as aSurfaceentity named after that solid, so the cube face is selected directly. No-slip boundary conditions are applied by default.``Freestream``: Applied to the farfield surface using
geo["farfield"]. This sets the farfield boundary condition with the velocity specified inoperating_condition.``rotating_farfield``: The rotation model defined in Section 3. This makes the entire fluid domain rotate.
``reference_geometry``:
ReferenceGeometry()enables calculation of reference quantities (forces, moments) for the cube geometry.
Note: The order of models in the list doesn’t matter, but all relevant models must be included.
[4]:
with fl.SI_unit_system:
params = fl.SimulationParams(
meshing=meshing_params, # Previously defined meshing parameters
operating_condition=fl.AerospaceCondition(velocity_magnitude=10 * fl.u.m / fl.u.s),
time_stepping=fl.Steady(),
models=[
fl.Wall(
surfaces=[geo["cube"]]
),
fl.Freestream(
surfaces=[geo["farfield"]]
),
rotating_farfield,
],
reference_geometry=fl.ReferenceGeometry(),
outputs=[
fl.SurfaceOutput(
surfaces=[geo["cube"]],
output_fields=['CfVec', 'Cf', 'yPlus', 'Cp']
)
]
)
INFO: using: SI unit system for unit inference.
5. Run Case#
Submit the case to Flow360’s cloud platform using project.run_case().
Key parameters:
``params``: The
SimulationParamsobject containing all simulation configuration.``name``: A descriptive name for the case (visible in the Flow360 web interface).
``solver_version``: Must match the version used when creating the project to ensure compatibility.
``use_beta_mesher=True``: Required when using
VolumeMeshingParams(the new volume mesher). This flag tells Flow360 to use the beta meshing pipeline instead of the default mesher.
What happens next:
The case is submitted and queued for execution.
Flow360 performs surface meshing using snappyHexMesh.
Volume meshing is performed using the new volume mesher.
The CFD solver runs the simulation.
Results are available for download and visualization.
[ ]:
case = project.run_case(params=params, name="SRF cube from Python", use_beta_mesher=True)
WARNING: The spacing of 50 mm specified in RegionRefinement will be cast to the first lower refinement in the octree series (31.25 mm).
WARNING: The spacing of 100 mm specified in RegionRefinement will be cast to the first lower refinement in the octree series (62.5 mm).
WARNING: The spacing of 50 mm specified in SurfaceEdgeRefinement will be cast to the first lower refinement in the octree series (31.25 mm).
WARNING: The spacing of 50 mm specified in UniformRefinement will be cast to the first lower refinement in the octree series (31.25 mm).
[06:06:12] INFO: Selecting beta/in-house mesher for possible meshing tasks.
[06:06:14] INFO: Successfully submitted: type = Case name = SRF cube from Python id = case-cf6239a4-538a-40bf-8e3f-bf1f33e954c4 status = pending project id = prj-fee2c42f-311f-4e60-8c4f-90f8512d066b
Image showing the friction lines on the front face of the cube, notice there is a swirl component. 