Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New testcase: External Aero Model, Generic F1 Rear Wing #520

Merged
merged 50 commits into from
Jul 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
a1f7b9e
New testcase : F1 RW
agvarghe Jun 21, 2023
0e0a565
Update examples/gallery/08_lucid_generic_f1_rear_wing.py
agvarghe Jul 11, 2023
468ac22
Update examples/gallery/08_lucid_generic_f1_rear_wing.py
agvarghe Jul 11, 2023
4327f68
Update examples/gallery/08_lucid_generic_f1_rear_wing.py
agvarghe Jul 11, 2023
ac32f90
Update examples/gallery/08_lucid_generic_f1_rear_wing.py
agvarghe Jul 11, 2023
3201c07
Update examples/gallery/08_lucid_generic_f1_rear_wing.py
agvarghe Jul 11, 2023
b9290b4
Update examples/gallery/08_lucid_generic_f1_rear_wing.py
agvarghe Jul 11, 2023
10b2278
Fix Display issue
agvarghe Jul 11, 2023
f562b06
Update 08_lucid_generic_f1_rear_wing.py
agvarghe Jul 11, 2023
b59fb8b
Fix Styling
agvarghe Jul 11, 2023
9890545
Update examples/gallery/08_lucid_generic_f1_rear_wing.py
agvarghe Jul 11, 2023
142fc56
Update examples/gallery/08_lucid_generic_f1_rear_wing.py
agvarghe Jul 11, 2023
c1ee7bd
Update examples/gallery/08_lucid_generic_f1_rear_wing.py
agvarghe Jul 11, 2023
b0bc926
Update examples/gallery/08_lucid_generic_f1_rear_wing.py
agvarghe Jul 11, 2023
7ac8773
Update examples/gallery/08_lucid_generic_f1_rear_wing.py
agvarghe Jul 11, 2023
fe5ece7
Update examples/gallery/08_lucid_generic_f1_rear_wing.py
agvarghe Jul 11, 2023
5a00c80
Update examples/gallery/08_lucid_generic_f1_rear_wing.py
agvarghe Jul 11, 2023
f5c2f92
Update examples/gallery/08_lucid_generic_f1_rear_wing.py
agvarghe Jul 11, 2023
ac774e2
Update examples/gallery/08_lucid_generic_f1_rear_wing.py
agvarghe Jul 11, 2023
2077cc7
Update examples/gallery/08_lucid_generic_f1_rear_wing.py
agvarghe Jul 11, 2023
680817a
Update examples/gallery/08_lucid_generic_f1_rear_wing.py
agvarghe Jul 11, 2023
d52a637
Update examples/gallery/08_lucid_generic_f1_rear_wing.py
agvarghe Jul 11, 2023
bfc861c
Update examples/gallery/08_lucid_generic_f1_rear_wing.py
waltersma Jul 12, 2023
7920e92
Update examples/gallery/08_lucid_generic_f1_rear_wing.py
waltersma Jul 12, 2023
a6738d1
Update examples/gallery/08_lucid_generic_f1_rear_wing.py
waltersma Jul 12, 2023
0ad9bfa
Update examples/gallery/08_lucid_generic_f1_rear_wing.py
waltersma Jul 12, 2023
a28dcca
Update examples/gallery/08_lucid_generic_f1_rear_wing.py
waltersma Jul 12, 2023
29962e2
Update examples/gallery/08_lucid_generic_f1_rear_wing.py
waltersma Jul 12, 2023
fac5777
Update examples/gallery/08_lucid_generic_f1_rear_wing.py
waltersma Jul 12, 2023
49a6d0a
Update examples/gallery/08_lucid_generic_f1_rear_wing.py
waltersma Jul 12, 2023
bb74769
Update examples/gallery/08_lucid_generic_f1_rear_wing.py
agvarghe Jul 12, 2023
7aea2d5
Merge branch 'main' into feat/example_stl_mesh
agvarghe Jul 12, 2023
8a1859e
Update 08_lucid_generic_f1_rear_wing.py
agvarghe Jul 13, 2023
9ab103d
Update 08_lucid_generic_f1_rear_wing.py
agvarghe Jul 13, 2023
be049e5
Update 08_lucid_generic_f1_rear_wing.py
agvarghe Jul 13, 2023
27a03b8
Fixed styling using black
agvarghe Jul 13, 2023
1e577e5
Merge branch 'main' into feat/example_stl_mesh
agvarghe Jul 13, 2023
fa29d2e
Update examples/gallery/08_lucid_generic_f1_rear_wing.py
waltersma Jul 13, 2023
4496e64
Update examples/gallery/08_lucid_generic_f1_rear_wing.py
waltersma Jul 13, 2023
b4c99a1
Update examples/gallery/08_lucid_generic_f1_rear_wing.py
waltersma Jul 13, 2023
a8f7fdc
Update examples/gallery/08_lucid_generic_f1_rear_wing.py
waltersma Jul 13, 2023
659f0e7
Update examples/gallery/08_lucid_generic_f1_rear_wing.py
waltersma Jul 13, 2023
92bab56
Update examples/gallery/08_lucid_generic_f1_rear_wing.py
waltersma Jul 13, 2023
23d0c44
Update examples/gallery/08_lucid_generic_f1_rear_wing.py
waltersma Jul 13, 2023
c614b66
Update examples/gallery/08_lucid_generic_f1_rear_wing.py
waltersma Jul 13, 2023
568c85f
Update examples/gallery/08_lucid_generic_f1_rear_wing.py
waltersma Jul 13, 2023
e70ab77
Update examples/gallery/08_lucid_generic_f1_rear_wing.py
waltersma Jul 13, 2023
209bde8
Update examples/gallery/08_lucid_generic_f1_rear_wing.py
waltersma Jul 13, 2023
0372caa
Update examples.py
srpyprime Jul 13, 2023
6307c75
Merge branch 'main' into feat/example_stl_mesh
ninad-kamat Jul 13, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added doc/source/images/generic_rear_wing.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
314 changes: 314 additions & 0 deletions examples/gallery/08_lucid_generic_f1_rear_wing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,314 @@
"""
.. _ref_generic_f1_rw:

================================================================
Meshing a generic F1 car rear wing for external aero simulation
================================================================

**Summary**: This example showcases the process of generating a mesh for a generic F1 rear wing
STL file model.

Objective
~~~~~~~~~~

The example demonstrates how to connect various parts of a rear wing from
a generic F1 car and volume mesh the resulting model using a poly-hexcore mesh containing prisms.
To simplify the process and enhance convenience, multiple meshing utilities provided in the
"lucid" class are used.

.. image:: ../../../images/generic_rear_wing.png
:align: center
:width: 800
:alt: Generic F1 rear wing.

Procedure
~~~~~~~~~~
* Launch an Ansys Prime Server instance and instantiate the meshing utilities
from the ``lucid`` class.
* Import and append the STL geometry files for each part of the F1 rear wing.
* Merge all imported components into a single part.
* Use the connect operation to join the components together.
* Define local size controls on aero surfaces.
* Generate a surface mesh with curvature sizing.
* Compute volume zones and define fluid zone type.
* Define boundary layer definition.
* Generate a volume mesh using poly-hexcore elements and apply boundary layer refinement.
* Print statistics on the generated mesh.
* Write a `.cas` file for use in the Fluent solver.
* Exit the PyPrimeMesh session.
"""

###############################################################################
# Launch Ansys Prime Server
# ~~~~~~~~~~~~~~~~~~~~~~~~~
# Import all necessary modules.
# Launch an instance of Ansys Prime Server.
# Connect the PyPrimeMesh client and get the model.
# Instantiate meshing utilities from the ``lucid`` class.

import os
import tempfile

import ansys.meshing.prime as prime
from ansys.meshing.prime.graphics import Graphics

prime_client = prime.launch_prime()
model = prime_client.model
mesh_util = prime.lucid.Mesh(model=model)

###############################################################################
# Import geometry
# ~~~~~~~~~~~~~~~
# Download the generic F1 rear wing geometries (stl files).
# Import each geometry and append to the model.
# Display the imported geometry.

f1_rw_drs = prime.examples.download_f1_rw_drs_stl()
f1_rw_enclosure = prime.examples.download_f1_rw_enclosure_stl()
f1_rw_end_plates = prime.examples.download_f1_rw_end_plates_stl()
f1_rw_main_plane = prime.examples.download_f1_rw_main_plane_stl()

for file_name in [f1_rw_drs, f1_rw_enclosure, f1_rw_end_plates, f1_rw_main_plane]:
mesh_util.read(file_name, append=True)

# display the rear wing geometry without the enclosure
display = Graphics(model)
scope = prime.ScopeDefinition(model, part_expression="* !*enclosure*")
display(scope=scope)

agvarghe marked this conversation as resolved.
Show resolved Hide resolved
###############################################################################
# Merge parts
# ~~~~~~~~~~~~~~~~~~~
# Establish the global size parameter to regulate mesh refinement.
# Merge all individual parts into a unified part named `f1_car_rear_wing`.

# Define global sizes
model.set_global_sizing_params(prime.GlobalSizingParams(model, min=4, max=32, growth_rate=1.2))

# Create label per part
for part in model.parts:
part.add_labels_on_zonelets([part.name.split(".")[0]], part.get_face_zonelets())

# Merge parts
merge_params = prime.MergePartsParams(model, merged_part_suggested_name="f1_car_rear_wing")
merge_result = model.merge_parts([part.id for part in model.parts], merge_params)
part = model.get_part_by_name(merge_result.merged_part_assigned_name)

###############################################################################
# Mesh connect
# ~~~~~~~~~~~~~~~~~~~
# In order to generate a volume mesh for a closed domain, it is necessary to ensure
# that the components of the rear wing are properly connected.
# To achieve this, perform a connect operation using labels to join the components of
# the rear wing.
# Afterward, inspect the mesh to detect any edges that are not connected.

# Connect faces
mesh_util.connect_faces(part.name, face_labels="*", target_face_labels="*", tolerance=0.02)

# Diagnostics
surf_diag = prime.SurfaceSearch(model)
surf_report = surf_diag.get_surface_diagnostic_summary(
prime.SurfaceDiagnosticSummaryParams(
model,
compute_free_edges=True,
compute_self_intersections=True,
)
)
print(f"Total number of free edges present is {surf_report.n_free_edges}")

agvarghe marked this conversation as resolved.
Show resolved Hide resolved
###############################################################################
# Define local size-control and generate size-field
# ~~~~~~~~~~~~~~~~~~~
# In order to accurately represent the physics of the DRS wing, a limitation of 8 mm
# is imposed on the mesh size of the wing.
# This is accomplished by implementing curvature size control, which refines the
# mesh according to the curvature of the DRS surfaces.
# Additionally, to accurately capture the curved surfaces of other sections of the
# wing, curvature control is defined with a normal angle of 18 degrees.
# These controls are used during surface mesh generation.
# A volumetric size-field is then computed based on the defined size controls.
# The volumetric size-field plays a crucial role in controlling
# the growth and refinement of the volume mesh.

# Local curvature size control for DRS
curv_size_control = model.control_data.create_size_control(prime.SizingType.CURVATURE)
curv_size_params = prime.CurvatureSizingParams(model, normal_angle=18, max=4)
curv_size_control.set_curvature_sizing_params(curv_size_params)
curv_scope = prime.ScopeDefinition(
model,
entity_type=prime.ScopeEntity.FACEZONELETS,
part_expression="f1_car_rear_wing*",
label_expression="*drs*",
)
curv_size_control.set_scope(curv_scope)
curv_size_control.set_suggested_name("curvature_drs")

# Global curvature size control on all face zones of the rear wing
curv_size_control_global = model.control_data.create_size_control(prime.SizingType.CURVATURE)
curv_size_params_global = prime.CurvatureSizingParams(model, normal_angle=18, min=8)
curv_size_control_global.set_curvature_sizing_params(curv_size_params_global)
curv_scope = prime.ScopeDefinition(
model,
entity_type=prime.ScopeEntity.FACEZONELETS,
part_expression="f1_car_rear_wing*",
)
curv_size_control_global.set_scope(curv_scope)
curv_size_control_global.set_suggested_name("curvature_global")

# Compute volumetric sizefield
compute_size = prime.SizeField(model)
vol_sf_params = prime.VolumetricSizeFieldComputeParams(model)
compute_size.compute_volumetric(
[curv_size_control.id, curv_size_control_global.id], volumetric_sizefield_params=vol_sf_params
)

###############################################################################
# Generate surface mesh
# ~~~~~~~~~~~~~~~~~~~
# Create a surface mesh for the rear wing using the defined size controls.
# To facilitate the definition of boundary conditions on the surfaces in the solver,
# generate face zones by utilizing the existing labels found in the rear wing model.

mesh_util.surface_mesh_with_size_controls(size_control_names="*curvature*")
scope = prime.ScopeDefinition(model, label_expression="* !*enclosure*")
display(scope=scope)

# Create face zones per label
for label in part.get_labels():
mesh_util.create_zones_from_labels(label_expression=label)

###############################################################################
# Compute volumetric regions
# ~~~~~~~~~~~~~~~~~~~
# Compute the volume zones.

mesh_util.compute_volumes(part_expression=part.name, create_zones_per_volume=True)

###############################################################################
# Define volume controls
# ~~~~~~~~~~~~~~~~~~~
# In order to prevent the generation of a volume mesh within the solid wing,
# the type of a volume zone within the rear wing can be defined as "dead".
# To accomplish this, Volume Control is utilized to assign the type for the
# specific volume zone.
# Expressions are employed to define the volume zones that need to be filled, with
# "* !f1_rw_enclosure" indicating that it applies to all volume zones except
# for "f1_rw_enclosure".

volume_control = model.control_data.create_volume_control()
volume_control.set_params(
prime.VolumeControlParams(
model,
cell_zonelet_type=prime.CellZoneletType.DEAD,
)
)
volume_control.set_scope(
prime.ScopeDefinition(
model, evaluation_type=prime.ScopeEvaluationType.ZONES, zone_expression="* !f1_rw_enclosure"
)
)

###############################################################################
# Define prism controls
# ~~~~~~~~~~~~~~~~~~~
# A prism control can be used to define inflation layers on the external aero surfaces.
# Specify the aero surfaces using labels, here prism scope is defined on zones associated
# with labels ``*drs*`` and ``*plane*``.
# The growth for the prism layer is controlled by defining the offset type to
# be ``uniform`` with a first height of 0.5mm .

prism_control = model.control_data.create_prism_control()
prism_control.set_surface_scope(
prime.ScopeDefinition(
model,
evaluation_type=prime.ScopeEvaluationType.LABELS,
entity_type=prime.ScopeEntity.FACEZONELETS,
label_expression="*drs*, *plane*",
)
)
prism_control.set_volume_scope(
prime.ScopeDefinition(
model,
evaluation_type=prime.ScopeEvaluationType.ZONES,
entity_type=prime.ScopeEntity.VOLUME,
zone_expression="*f1_rw_enclosure*",
)
)
prism_control.set_growth_params(
prime.PrismControlGrowthParams(
model,
offset_type=prime.PrismControlOffsetType.UNIFORM,
n_layers=5,
first_height=0.5,
growth_rate=1.2,
)
)

###############################################################################
# Generate volume mesh
# ~~~~~~~~~~~~~~~~~~~
# Volume mesh with hexcore polyhedral elements and boundary layer refinement.

volume_mesh = prime.AutoMesh(model)
auto_mesh_param = prime.AutoMeshParams(
model,
prism_control_ids=[prism_control.id],
size_field_type=prime.SizeFieldType.VOLUMETRIC,
volume_fill_type=prime.VolumeFillType.HEXCOREPOLY,
volume_control_ids=[volume_control.id],
)
volume_mesh.mesh(part.id, auto_mesh_param)

###############################################################################
# Print mesh statistics
# ~~~~~~~~~~~~~~~~~~~~~

# Get meshed part
part = model.get_part_by_name("f1_car_rear_wing")

# Get statistics on the mesh
part_summary_res = part.get_summary(prime.PartSummaryParams(model=model))

# Get element quality on all parts in the model
search = prime.VolumeSearch(model=model)
params = prime.VolumeQualitySummaryParams(
model=model,
scope=prime.ScopeDefinition(model=model, part_expression="*"),
cell_quality_measures=[prime.CellQualityMeasure.INVERSEORTHOGONAL],
quality_limit=[0.9],
)
results = search.get_volume_quality_summary(params=params)

# Print statistics on meshed part
print(part_summary_res)
print(
"\nMaximum inverse-orthoginal quality of the Volume Mesh : ",
results.quality_results_part[0].max_quality,
)

# Mesh check
result = prime.VolumeMeshTool(model).check_mesh(part.id, params=prime.CheckMeshParams(model))
print("\nMesh Check", result, sep="\n")

scope = prime.ScopeDefinition(model, part_expression="*", label_expression="* !*enclosure*")
display(scope=scope)

###############################################################################
# Write mesh
# ~~~~~~~~~~
# Export as cas file for external aero simulations

with tempfile.TemporaryDirectory() as temp_folder:
print(temp_folder)
mesh_file = os.path.join(temp_folder, "f1_rear_wing_vol_mesh.cas")
mesh_util.write(mesh_file)
assert os.path.exists(mesh_file)
print("\nExported file:\n", mesh_file)


###############################################################################
# Exit PyPrimeMesh
# ~~~~~~~~~~~~~~~~

prime_client.exit()
4 changes: 4 additions & 0 deletions src/ansys/meshing/prime/examples/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
download_elbow_fmd,
download_elbow_pmdat,
download_elbow_scdoc,
download_f1_rw_drs_stl,
download_f1_rw_enclosure_stl,
download_f1_rw_end_plates_stl,
download_f1_rw_main_plane_stl,
download_pcb_pmdat,
download_pcb_scdoc,
download_pipe_tee_dsco,
Expand Down
Loading
Loading