.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "examples/gallery_examples/gallery/04_lucid_toy_car.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code .. rst-class:: sphx-glr-example-title .. _sphx_glr_examples_gallery_examples_gallery_04_lucid_toy_car.py: .. _ref_toy_car_wrap: ================================== Wrap a toy car for a flow analysis ================================== **Summary**: This example demonstrates how to wrap a toy car for a flow analysis. Objective ~~~~~~~~~ This example wraps a toy car and volume meshes with a tetrahedral mesh with prisms. It uses several meshing utilities available in the ``lucid`` class for convenience and ease. .. image:: ../../../images/toy_car.png :align: center :width: 400 :alt: Toy car wrap. Procedure ~~~~~~~~~ * Launch an Ansys Prime Server instance and instantiate the meshing utilities from the ``lucid`` class. * Import the geometry. * Coarse wrap parts with holes to clean up. * Extract the fluid region using a wrapper. * Check that the wrap surface is closed and that the quality is suitable. * Mesh only fluid with tetrahedral elements and boundary layer refinement. * Create face zones from labels imported from the geometry. * Print statistics on the generated mesh. * Improve the mesh quality. * Write a CAS file for use in the Fluent solver. * Exit the PyPrimeMesh session. .. GENERATED FROM PYTHON SOURCE LINES 59-64 Launch Ansys Prime Server ~~~~~~~~~~~~~~~~~~~~~~~~~ Import all necessary modules and launch an instance of Ansys Prime Server. From the PyPrimeMesh client get the model. Instantiate meshing utilities from the ``lucid`` class. .. GENERATED FROM PYTHON SOURCE LINES 64-77 .. code-block:: Python 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 display = Graphics(model=model) mesh_util = prime.lucid.Mesh(model) .. GENERATED FROM PYTHON SOURCE LINES 78-82 Import geometry ~~~~~~~~~~~~~~~ Download the toy car geometry (FMD) file exported by SpaceClaim. Import the geometry and display everything except the tunnel. .. GENERATED FROM PYTHON SOURCE LINES 82-94 .. code-block:: Python # For Windows OS users, scdoc is also available: # toy_car = prime.examples.download_toy_car_scdoc() toy_car = prime.examples.download_toy_car_fmd() mesh_util.read(file_name=toy_car) scope = prime.ScopeDefinition(model, part_expression="* !*tunnel*") display(scope=scope) .. image-sg:: /examples/gallery_examples/gallery/images/sphx_glr_04_lucid_toy_car_001.png :alt: 04 lucid toy car :srcset: /examples/gallery_examples/gallery/images/sphx_glr_04_lucid_toy_car_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 95-103 Close holes ~~~~~~~~~~~ Several parts are open surfaces (with holes). Coarse wrap to close the holes and delete the originals. You could use leakage detection to close these regions. This example uses a coarse wrap and disables feature edge refinement to walk over the holes. As this is not the final wrap, this example does not remesh after the wrap. Wrapping each object in turn avoids coarse wrap bridging across narrow gaps. .. GENERATED FROM PYTHON SOURCE LINES 103-118 .. code-block:: Python coarse_wrap = {"cabin": 1.5, "exhaust": 0.6, "engine": 1.5} for part_name in coarse_wrap: # Each open part before wrap display(scope=prime.ScopeDefinition(model, part_expression=part_name)) closed_part = mesh_util.wrap( input_parts=part_name, max_size=coarse_wrap[part_name], remesh_postwrap=False, enable_feature_octree_refinement=False, ) # Closed part with no hole display(scope=prime.ScopeDefinition(model, part_expression=closed_part.name)) .. rst-class:: sphx-glr-horizontal * .. image-sg:: /examples/gallery_examples/gallery/images/sphx_glr_04_lucid_toy_car_002.png :alt: 04 lucid toy car :srcset: /examples/gallery_examples/gallery/images/sphx_glr_04_lucid_toy_car_002.png :class: sphx-glr-multi-img * .. image-sg:: /examples/gallery_examples/gallery/images/sphx_glr_04_lucid_toy_car_003.png :alt: 04 lucid toy car :srcset: /examples/gallery_examples/gallery/images/sphx_glr_04_lucid_toy_car_003.png :class: sphx-glr-multi-img * .. image-sg:: /examples/gallery_examples/gallery/images/sphx_glr_04_lucid_toy_car_004.png :alt: 04 lucid toy car :srcset: /examples/gallery_examples/gallery/images/sphx_glr_04_lucid_toy_car_004.png :class: sphx-glr-multi-img * .. image-sg:: /examples/gallery_examples/gallery/images/sphx_glr_04_lucid_toy_car_005.png :alt: 04 lucid toy car :srcset: /examples/gallery_examples/gallery/images/sphx_glr_04_lucid_toy_car_005.png :class: sphx-glr-multi-img * .. image-sg:: /examples/gallery_examples/gallery/images/sphx_glr_04_lucid_toy_car_006.png :alt: 04 lucid toy car :srcset: /examples/gallery_examples/gallery/images/sphx_glr_04_lucid_toy_car_006.png :class: sphx-glr-multi-img * .. image-sg:: /examples/gallery_examples/gallery/images/sphx_glr_04_lucid_toy_car_007.png :alt: 04 lucid toy car :srcset: /examples/gallery_examples/gallery/images/sphx_glr_04_lucid_toy_car_007.png :class: sphx-glr-multi-img .. GENERATED FROM PYTHON SOURCE LINES 119-126 Extract fluid using a wrapper ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Wrap the full model and extract the largest internal region as the fluid. Create edges at intersecting regions to improve the quality. Refine mesh to avoid contact between different parts. The new wrap object replaces all original geometry unless ``keep_input`` is set to ``True``. Volumes are generated from the wrap for use later. .. GENERATED FROM PYTHON SOURCE LINES 126-137 .. code-block:: Python wrap_part = mesh_util.wrap( min_size=0.1, max_size=2.0, region_extract=prime.WrapRegion.LARGESTINTERNAL, create_intersection_loops=True, contact_prevention_size=0.1, ) print(model) .. rst-class:: sphx-glr-script-out .. code-block:: none Part Summary: Part Name: __wrap__.3 Part ID: 23 1 Edge Zonelets 93 Face Zonelets 0 Cell Zonelets 0 Edge Zones Edge Zone Name(s) : [] 5 Face Zones Face Zone Name(s) : [surface, surface.1, cabin, exhaust, engine] 6 Volume Zones Volume Zone Name(s) : [__wrap__.2, __wrap__.1, __wrap__, component25, component24, tunnel.1] 24 Label(s) Names: [___geom_features___, __extracted__features__, __intersect_loops__, __wrap__, __wrap__.1, __wrap__.2, cabin, component21, component22, component24, component25, engine, exhaust, ground, inlet, outer, outlet, overlap_floor, tunnel, unreferenced, wheel_1, wheel_2, wheel_3, wheel_4] Bounding box (-31.1366 -59.1336 1.49005) (29.3366 40.1337 52.0558) .. GENERATED FROM PYTHON SOURCE LINES 138-142 Check wrap ~~~~~~~~~~ Check that the wrap surface is closed and that the quality is suitable to use as surface mesh. .. GENERATED FROM PYTHON SOURCE LINES 142-172 .. code-block:: Python scope = prime.ScopeDefinition(model=model, part_expression=wrap_part.name) diag = prime.SurfaceSearch(model) diag_params = prime.SurfaceDiagnosticSummaryParams( model, scope=scope, compute_free_edges=True, compute_multi_edges=True, compute_self_intersections=True, ) diag_res = diag.get_surface_diagnostic_summary(diag_params) print('Number of free edges', diag_res.n_free_edges) print('Number of multi edges', diag_res.n_multi_edges) print('Number of self intersections', diag_res.n_self_intersections) face_quality_measures = [prime.FaceQualityMeasure.SKEWNESS, prime.FaceQualityMeasure.ASPECTRATIO] quality_params = prime.SurfaceQualitySummaryParams( model=model, scope=scope, face_quality_measures=face_quality_measures, quality_limit=[0.9, 20] ) quality = prime.SurfaceSearch(model) qual_summary_res = quality.get_surface_quality_summary(quality_params) for summary_res in qual_summary_res.quality_results: print("\nMax value of ", summary_res.measure_name, ": ", summary_res.max_quality) print("Faces above limit: ", summary_res.n_found) .. rst-class:: sphx-glr-script-out .. code-block:: none Number of free edges 0 Number of multi edges 0 Number of self intersections 0 Max value of Skewness : 0.892958 Faces above limit: 0 Max value of AspectRatio : 5.9153 Faces above limit: 0 .. GENERATED FROM PYTHON SOURCE LINES 173-182 Create zones ~~~~~~~~~~~~ Create face zones from labels imported from the geometry that can be used in the solver to define boundary conditions. If specifying individual labels to create zones, the order is important. The last label in the list wins. Providing no ``label_expression`` flattens all labels into zones. For example, if ``LabelA`` and ``LabelB`` are overlapping, three zones are created: ``LabelA``, ``LabelB``, and ``LabelA_LabelB``. .. GENERATED FROM PYTHON SOURCE LINES 182-187 .. code-block:: Python mesh_util.create_zones_from_labels() print(model) .. rst-class:: sphx-glr-script-out .. code-block:: none Part Summary: Part Name: __wrap__.3 Part ID: 23 1 Edge Zonelets 93 Face Zonelets 0 Cell Zonelets 0 Edge Zones Edge Zone Name(s) : [] 21 Face Zones Face Zone Name(s) : [surface, surface.1, cabin, exhaust, engine, __wrap__.2_engine_unreferenced, __wrap__.1_exhaust_unreferenced, __wrap___cabin_unreferenced, unreferenced_wheel_2, unreferenced_wheel_3, unreferenced_wheel_4, unreferenced_wheel_1, outer_unreferenced, component24_unreferenced, component25_unreferenced, tunnel_unreferenced, ground_overlap_floor_tunnel, inlet_tunnel, component21_unreferenced, component22_unreferenced, outlet_tunnel] 6 Volume Zones Volume Zone Name(s) : [__wrap__.2, __wrap__.1, __wrap__, component25, component24, tunnel.1] 24 Label(s) Names: [___geom_features___, __extracted__features__, __intersect_loops__, __wrap__, __wrap__.1, __wrap__.2, cabin, component21, component22, component24, component25, engine, exhaust, ground, inlet, outer, outlet, overlap_floor, tunnel, unreferenced, wheel_1, wheel_2, wheel_3, wheel_4] Bounding box (-31.1366 -59.1336 1.49005) (29.3366 40.1337 52.0558) .. GENERATED FROM PYTHON SOURCE LINES 188-195 Volume mesh ~~~~~~~~~~~ Mesh only fluid volume with tetrahedral elements and boundary layer refinement. This example does not mesh other volumetric regions. Volume zones exist already for volume meshing and passing to the solver. The largest face zonelet is used by default to define volume zone names at creation. After volume meshing, you can see that you have a cell zonelet in the part summary. .. GENERATED FROM PYTHON SOURCE LINES 195-219 .. code-block:: Python volume = prime.lucid.VolumeScope( part_expression=wrap_part.name, entity_expression="tunnel*", scope_evaluation_type=prime.ScopeEvaluationType.ZONES, ) # Use expressions to define which surfaces to grow inflation layers from mesh_util.volume_mesh( scope=volume, prism_layers=3, prism_surface_expression="*cabin*,*component*,*engine*,*exhaust*,*ground*,*outer*,*wheel*", prism_volume_expression="tunnel*", ) scope = prime.ScopeDefinition( model, label_expression="*cabin*,*component*,*engine*,*exhaust*,*ground*,*outer*,*wheel*,*outlet*", ) display(update=True, scope=scope) print(model) .. image-sg:: /examples/gallery_examples/gallery/images/sphx_glr_04_lucid_toy_car_008.png :alt: 04 lucid toy car :srcset: /examples/gallery_examples/gallery/images/sphx_glr_04_lucid_toy_car_008.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Part Summary: Part Name: __wrap__.3 Part ID: 23 1 Edge Zonelets 93 Face Zonelets 1 Cell Zonelets 0 Edge Zones Edge Zone Name(s) : [] 21 Face Zones Face Zone Name(s) : [surface, surface.1, cabin, exhaust, engine, __wrap__.2_engine_unreferenced, __wrap__.1_exhaust_unreferenced, __wrap___cabin_unreferenced, unreferenced_wheel_2, unreferenced_wheel_3, unreferenced_wheel_4, unreferenced_wheel_1, outer_unreferenced, component24_unreferenced, component25_unreferenced, tunnel_unreferenced, ground_overlap_floor_tunnel, inlet_tunnel, component21_unreferenced, component22_unreferenced, outlet_tunnel] 6 Volume Zones Volume Zone Name(s) : [__wrap__.2, __wrap__.1, __wrap__, component25, component24, tunnel.1] 24 Label(s) Names: [___geom_features___, __extracted__features__, __intersect_loops__, __wrap__, __wrap__.1, __wrap__.2, cabin, component21, component22, component24, component25, engine, exhaust, ground, inlet, outer, outlet, overlap_floor, tunnel, unreferenced, wheel_1, wheel_2, wheel_3, wheel_4] Bounding box (-31.1366 -59.1336 1.49005) (29.3366 40.1337 52.0558) .. GENERATED FROM PYTHON SOURCE LINES 220-223 Print mesh stats ~~~~~~~~~~~~~~~~ Print statistics on the generated mesh. .. GENERATED FROM PYTHON SOURCE LINES 223-254 .. code-block:: Python vtool = prime.VolumeMeshTool(model=model) result = vtool.check_mesh(part_id=wrap_part.id, params=prime.CheckMeshParams(model=model)) print("Non positive volumes:", result.has_non_positive_volumes) print("Non positive areas:", result.has_non_positive_areas) print("Invalid shape:", result.has_invalid_shape) print("Left handed faces:", result.has_left_handed_faces) quality = prime.VolumeSearch(model) scope = prime.ScopeDefinition(model, part_expression=wrap_part.name) part_summary_res = wrap_part.get_summary( prime.PartSummaryParams(model=model, print_id=False, print_mesh=True) ) print("\nNo. of cells : ", part_summary_res.n_cells) qual_summary_res = quality.get_volume_quality_summary( prime.VolumeQualitySummaryParams( model=model, scope=scope, cell_quality_measures=[prime.CellQualityMeasure.SKEWNESS], quality_limit=[0.95], ) ) for summary_res in qual_summary_res.quality_results_part: print("\nMax value of ", summary_res.measure_name, ": ", summary_res.max_quality) print("Cells above limit: ", summary_res.n_found) .. rst-class:: sphx-glr-script-out .. code-block:: none Non positive volumes: False Non positive areas: False Invalid shape: False Left handed faces: False No. of cells : 3331834 Max value of Skewness : 0.999323 Cells above limit: 75 .. GENERATED FROM PYTHON SOURCE LINES 255-259 Improve quality ~~~~~~~~~~~~~~~ Because the mesh quality is poor, use the ``improve_by_auto_node_move`` method to improve the mesh. .. GENERATED FROM PYTHON SOURCE LINES 259-298 .. code-block:: Python improve = prime.VolumeMeshTool(model=model) params = prime.AutoNodeMoveParams( model=model, quality_measure=prime.CellQualityMeasure.SKEWNESS, target_quality=0.95, dihedral_angle=90, n_iterations_per_node=50, restrict_boundary_nodes_along_surface=True, n_attempts=10, ) improve.improve_by_auto_node_move( part_id=wrap_part.id, cell_zonelets=wrap_part.get_cell_zonelets(), boundary_zonelets=wrap_part.get_face_zonelets(), params=params, ) result = vtool.check_mesh(part_id=wrap_part.id, params=prime.CheckMeshParams(model=model)) print("Non positive volumes:", result.has_non_positive_volumes) print("Non positive areas:", result.has_non_positive_areas) print("Invalid shape:", result.has_invalid_shape) print("Left handed faces:", result.has_left_handed_faces) qual_summary_res = quality.get_volume_quality_summary( prime.VolumeQualitySummaryParams( model=model, scope=scope, cell_quality_measures=[prime.CellQualityMeasure.SKEWNESS], quality_limit=[0.95], ) ) for summary_res in qual_summary_res.quality_results_part: print("\nMax value of ", summary_res.measure_name, ": ", summary_res.max_quality) print("Cells above limit: ", summary_res.n_found) .. rst-class:: sphx-glr-script-out .. code-block:: none Non positive volumes: False Non positive areas: False Invalid shape: False Left handed faces: False Max value of Skewness : 0.949972 Cells above limit: 0 .. GENERATED FROM PYTHON SOURCE LINES 299-302 Write mesh ~~~~~~~~~~ Write a CAS file for use in the Fluent solver. .. GENERATED FROM PYTHON SOURCE LINES 302-309 .. code-block:: Python with tempfile.TemporaryDirectory() as temp_folder: mesh_file = os.path.join(temp_folder, "toy_car_lucid.cas") mesh_util.write(mesh_file) assert os.path.exists(mesh_file) print("\nExported file:\n", mesh_file) .. rst-class:: sphx-glr-script-out .. code-block:: none Exported file: /tmp/tmpmsnzk9zo/toy_car_lucid.cas .. GENERATED FROM PYTHON SOURCE LINES 310-312 Exit PyPrimeMesh ~~~~~~~~~~~~~~~~ .. GENERATED FROM PYTHON SOURCE LINES 312-314 .. code-block:: Python prime_client.exit() .. rst-class:: sphx-glr-timing **Total running time of the script:** (2 minutes 27.837 seconds) .. _sphx_glr_download_examples_gallery_examples_gallery_04_lucid_toy_car.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: 04_lucid_toy_car.ipynb <04_lucid_toy_car.ipynb>` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: 04_lucid_toy_car.py <04_lucid_toy_car.py>` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_