Time Averaged Isosurfaces

Contents

Time Averaged Isosurfaces#

This example demonstrates how to compute time averaged isosurfaces from an unsteady simulation using the Flow360 Python API. It details the setup for the variables to compute the isosurfaces and also specifying desired output fields (like primitive variables, Mach number, Cp, Cf). The case is based on an isolated propeller example and the time averaged isosurfaces are taken for one rotor revolution.

  1import tarfile
  2
  3import flow360 as fl
  4from flow360.examples import IsolatedPropeller
  5
  6IsolatedPropeller.get_files()
  7
  8project = fl.Project.from_geometry(IsolatedPropeller.geometry, name="Time-averaged isosurfaces")
  9
 10geometry = project.geometry
 11geometry.group_edges_by_tag("edgeId")
 12geometry.group_faces_by_tag("faceName")
 13
 14with fl.SI_unit_system:
 15    rotating_cylinder = fl.Cylinder(
 16        name="Rotating zone", center=[0, 0, 0], axis=[1, 0, 0], outer_radius=2, height=0.8
 17    )
 18    refinement_cylinder = fl.Cylinder(
 19        name="Refinement zone", center=[1.9, 0, 0], axis=[1, 0, 0], outer_radius=2, height=4
 20    )
 21    slice = fl.Slice(name="Slice", normal=[1, 0, 0], origin=[0.6, 0, 0])
 22    volume_zone_rotating_cylinder = fl.RotationCylinder(
 23        name="Rotation cylinder",
 24        spacing_axial=0.05,
 25        spacing_radial=0.05,
 26        spacing_circumferential=0.05,
 27        entities=[rotating_cylinder],
 28        enclosed_entities=[geometry["*"]],
 29    )
 30    farfield = fl.AutomatedFarfield(name="Farfield")
 31    params = fl.SimulationParams(
 32        meshing=fl.MeshingParams(
 33            defaults=fl.MeshingDefaults(
 34                surface_max_edge_length=1, boundary_layer_first_layer_thickness=0.1 * fl.u.mm
 35            ),
 36            refinements=[
 37                fl.UniformRefinement(
 38                    name="Uniform refinement", spacing=0.025, entities=[refinement_cylinder]
 39                )
 40            ],
 41            volume_zones=[farfield, volume_zone_rotating_cylinder],
 42        ),
 43        reference_geometry=fl.ReferenceGeometry(
 44            area=1, moment_center=[0, 0, 0], moment_length=[1, 1, 1]
 45        ),
 46        operating_condition=fl.AerospaceCondition(velocity_magnitude=20),
 47        models=[
 48            fl.Wall(name="Wall", surfaces=[geometry["*"]]),
 49            fl.Freestream(name="Freestream", surfaces=[farfield.farfield]),
 50            fl.Fluid(
 51                navier_stokes_solver=fl.NavierStokesSolver(relative_tolerance=0.01),
 52                turbulence_model_solver=fl.SpalartAllmaras(
 53                    relative_tolerance=0.01, hybrid_model=fl.DetachedEddySimulation()
 54                ),
 55            ),
 56            fl.Rotation(
 57                name="Rotation",
 58                volumes=[rotating_cylinder],
 59                spec=fl.AngularVelocity(value=200 * fl.u.rpm),
 60            ),
 61        ],
 62        time_stepping=fl.Unsteady(
 63            steps=600,
 64            step_size=0.0025,
 65            max_pseudo_steps=35,
 66            CFL=fl.AdaptiveCFL(
 67                min=0.1, max=10000, max_relative_change=1, convergence_limiting_factor=0.5
 68            ),
 69        ),
 70        outputs=[
 71            fl.SurfaceOutput(
 72                name="Surface output",
 73                output_fields=["Cp", "yPlus", "Cf", "CfVec"],
 74                surfaces=[geometry["*"]],
 75            ),
 76            fl.SliceOutput(
 77                name="Slice output",
 78                output_fields=["qcriterion", "vorticity", "Mach"],
 79                slices=[slice],
 80            ),
 81            fl.TimeAverageIsosurfaceOutput(
 82                isosurfaces=[
 83                    fl.Isosurface(name="q_criterion_avg", field="qcriterion", iso_value=0.0004128)
 84                ],
 85                start_step=420,
 86                output_fields=["velocity_magnitude"],
 87                output_format="both",
 88            ),
 89        ],
 90    )
 91
 92case = project.run_case(params, name="Time-averaged isosurfaces")
 93case.wait()
 94results = case.results
 95
 96# download slice and isosurfaces output files as tar.gz archives
 97results.slices.download("slices.tar.gz", overwrite=True)
 98results.isosurfaces.download("isosurfaces.tar.gz", overwrite=True)
 99
100# extract slices file
101file = tarfile.open("slices.tar.gz")
102file.extractall("slices")
103file.close()
104
105# extract isosurfaces file
106file = tarfile.open("isosurfaces.tar.gz")
107file.extractall("isosurfaces")
108file.close()

Notes#

  • The fl.Isosurface is used to define the isosurfaces with the field and value. The fields in output_fields will be computed on the averaged isosurface.

  • The start_step is used to specify the step from which the average will be computed, in this case it corresponds to last rotor revolution.

  • The results are downloaded in the file direcotry and can be opened in either paraview or tecplot.