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 inoutput_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.