generated from ansys/template
-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
463 additions
and
0 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,315 @@ | ||
""" | ||
.. _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 given example demonstrates the interconnection between various elements of the rear wing of | ||
a generic F1 car, along with volume meshes, utilizing a poly-hexcore mesh containing prisms.To | ||
simplify the process and enhance convenience, multiple meshing utilities provided in the | ||
"lucid" class are employed. | ||
.. 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 the STL geometry file for each component of the F1 rear wing. | ||
* Merge all imported components into a single part. | ||
* Use the connect operation to join the components together. | ||
* Generate a surface mesh with curvature sizing to refine the mesh based on curvature. | ||
* Extract Fluid Region by defining a material pount. | ||
* 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 exported from SpaceClaim. | ||
# Import each geometry from the example folder. | ||
# 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 = Graphics(model) | ||
scope = prime.ScopeDefinition(model, part_expression="* !*enclosure*") | ||
|
||
############################################################################### | ||
# 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.05) | ||
|
||
# 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}") | ||
|
||
############################################################################### | ||
# 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. | ||
# A volumetric size field is then computed based on the defined size control. | ||
|
||
# Local Curvature size control on all components | ||
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") | ||
|
||
# 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") | ||
|
||
# Compute volumetric sizefield | ||
compute_size = prime.SizeField(model) | ||
vol_sf_params = prime.VolumetricSizeFieldComputeParams(model) | ||
compute_size.compute_volumetric([curv_size_control.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*") | ||
|
||
# Create face-zones per label | ||
for label in part.get_labels(): | ||
mesh_util.create_zones_from_labels(label_expression=label) | ||
|
||
scope = prime.ScopeDefinition(model, part_expression="*", label_expression="* !*enclosure*") | ||
display( | ||
scope=scope, | ||
) | ||
############################################################################### | ||
# 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_1 = model.control_data.create_volume_control() | ||
volume_control_1.set_params( | ||
prime.VolumeControlParams( | ||
model, | ||
cell_zonelet_type=prime.CellZoneletType.DEAD, | ||
) | ||
) | ||
volume_control_1.set_scope( | ||
prime.ScopeDefinition( | ||
model, evaluation_type=prime.ScopeEvaluationType.ZONES, zone_expression="* !f1_rw_enclosure" | ||
) | ||
) | ||
|
||
|
||
############################################################################### | ||
# Define Prism Controls | ||
# ~~~~~~~~~~~~~~~~~~~ | ||
# 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 control by defining 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 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_1.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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.