BET eVTOL

Contents

BET eVTOL#

In this example we simulate multiple Blade Element Theory (BET) disks for an eVTOL (electric Vertical Take-Off and Landing) aircraft using the Flow360 Python API. It covers loading geometry, defining mesh refinements including axisymmetric refinement for multiple rotor regions, specifying operating conditions, creating multiple BET disks from cylinder entities defined for each of the blades and predefined BET disk files. To see how to create a BET disk directly from an xrotor file, check the BET Disk example.

  1import flow360 as fl
  2from flow360.examples import BETEVTOL
  3
  4BETEVTOL.get_files()
  5
  6project = fl.Project.from_geometry(BETEVTOL.geometry, name="BET eVTOL")
  7
  8geometry = project.geometry
  9geometry.group_edges_by_tag("edgeId")
 10geometry.group_faces_by_tag("faceId")
 11
 12
 13with fl.SI_unit_system:
 14    box1 = fl.Box(name="Box 1", center=[2, 0, 0.5], size=[12, 16, 4])
 15    box2 = fl.Box(name="Box 2", center=[8, 0, 0.5], size=[24, 32, 8])
 16    cylinder1 = fl.Cylinder(
 17        name="BET 1", center=[-1.95, -6, 0.57], axis=[-1, 0, 0], outer_radius=1.5, height=0.2
 18    )
 19    cylinder2 = fl.Cylinder(
 20        name="BET 2", center=[-1.95, -2.65, 0.51], axis=[-1, 0, 0], outer_radius=1.5, height=0.2
 21    )
 22    cylinder3 = fl.Cylinder(
 23        name="BET 3", center=[-1.95, 2.65, 0.51], axis=[-1, 0, 0], outer_radius=1.5, height=0.2
 24    )
 25    cylinder4 = fl.Cylinder(
 26        name="BET 4", center=[-1.95, 6, 0.57], axis=[-1, 0, 0], outer_radius=1.5, height=0.2
 27    )
 28    cylinder5 = fl.Cylinder(
 29        name="BET 5", center=[2.7, -6, 1.06], axis=[0, 0, 1], outer_radius=1.5, height=0.2
 30    )
 31    cylinder6 = fl.Cylinder(
 32        name="BET 6", center=[2.7, -2.65, 1.06], axis=[0, 0, 1], outer_radius=1.5, height=0.2
 33    )
 34    cylinder7 = fl.Cylinder(
 35        name="BET 7", center=[2.7, 2.65, 1.06], axis=[0, 0, 1], outer_radius=1.5, height=0.2
 36    )
 37    cylinder8 = fl.Cylinder(
 38        name="BET 8", center=[2.7, 6, 1.06], axis=[0, 0, 1], outer_radius=1.5, height=0.2
 39    )
 40    slices = [
 41        fl.Slice(name=f"Slice BET {i+1}", normal=[0, 1, 0], origin=[0, originY, 0])
 42        for i, originY in enumerate([-6, -2.65, 2.65, 6])
 43    ]
 44    farfield = fl.AutomatedFarfield(name="Farfield")
 45    params = fl.SimulationParams(
 46        meshing=fl.MeshingParams(
 47            defaults=fl.MeshingDefaults(
 48                surface_max_edge_length=0.05, boundary_layer_first_layer_thickness=0.01 * fl.u.mm
 49            ),
 50            volume_zones=[farfield],
 51            refinements=[
 52                fl.AxisymmetricRefinement(
 53                    name="BET refinement",
 54                    spacing_axial=0.01,
 55                    spacing_radial=0.03,
 56                    spacing_circumferential=0.03,
 57                    entities=[
 58                        cylinder1,
 59                        cylinder2,
 60                        cylinder3,
 61                        cylinder4,
 62                        cylinder5,
 63                        cylinder6,
 64                        cylinder7,
 65                        cylinder8,
 66                    ],
 67                ),
 68                fl.UniformRefinement(name="Uniform refinement 0.05", spacing=0.05, entities=box1),
 69                fl.UniformRefinement(name="Uniform refinement 0.1", spacing=0.1, entities=box2),
 70            ],
 71        ),
 72        reference_geometry=fl.ReferenceGeometry(
 73            area=16.8, moment_center=[0, 0, 0], moment_length=[1.4, 1.4, 1.4]
 74        ),
 75        operating_condition=fl.AerospaceCondition(velocity_magnitude=70, alpha=15 * fl.u.deg),
 76        models=[
 77            fl.Wall(name="Wall", surfaces=[geometry["*"]]),
 78            fl.Freestream(name="Freestream", surfaces=[farfield.farfield]),
 79            fl.Fluid(
 80                navier_stokes_solver=fl.NavierStokesSolver(relative_tolerance=0.01),
 81                turbulence_model_solver=fl.SpalartAllmaras(
 82                    relative_tolerance=0.01,
 83                    rotation_correction=True,
 84                    hybrid_model=fl.DetachedEddySimulation(),
 85                ),
 86            ),
 87            fl.BETDisk.from_file(BETEVTOL.extra["disk13"]),
 88            fl.BETDisk.from_file(BETEVTOL.extra["disk24"]),
 89            fl.BETDisk.from_file(BETEVTOL.extra["disk57"]),
 90            fl.BETDisk.from_file(BETEVTOL.extra["disk68"]),
 91        ],
 92        time_stepping=fl.Unsteady(
 93            steps=1000,
 94            step_size=0.0004,
 95            max_pseudo_steps=30,
 96            CFL=fl.AdaptiveCFL(
 97                min=1, max=3000, max_relative_change=50, convergence_limiting_factor=0.1
 98            ),
 99        ),
100        outputs=[
101            fl.SurfaceOutput(
102                name="Surface output",
103                output_fields=["Cp", "yPlus", "Cf", "CfVec"],
104                surfaces=[geometry["*"]],
105            ),
106            fl.SliceOutput(
107                name="Slice output", output_fields=["Cp", "Mach", "vorticity"], slices=[*slices]
108            ),
109        ],
110    )
111
112
113project.run_case(params, name="BET eVTOL case")

Notes#

  • There are 8 rotor disks arranged in a typical eVTOL configuration with both front and rear rotor positions.

  • BET disk parameters are loaded from external BET disk files for different rotor configurations.

  • AxisymmetricRefinement is used to control mesh resolution within the cylindrical BET disk regions.