.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "examples/gallery_examples/gallery/09_multi_layer_quad_mesh_pcb.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_09_multi_layer_quad_mesh_pcb.py: .. _ref_multi_layer_pcb_mesh: ===================================================== Mesh a generic PCB geometry with multiple hexa layers ===================================================== **Summary**: This example demonstrates how to set the base mesh size and number of layers for each solid in a generic PCB geometry and then generate a mesh. Objective ~~~~~~~~~~ The example uses PyPrimeMesh to discretize a PCB CAD geometry by means of the stacker technology. You can easily set up the mesh size of the base face (xy plane in this example) and the number of mesh layers along the sweep direction (z axis in this example). The CAD edges along the z direction are assigned with a named selection at a CAD level in Ansys Discovery/SpaceClaim. The following image provides a snapshot of the Discovery tree to help you to understand the model's organization. Share topology in Discovery/SpaceClaim guarantees the generation of a conformal mesh between the solids. Named selections of edges allow you to specify the number of mesh elements to generate along the sweep direction. To simplify the process and enhance convenience, this example uses multiple meshing utilities provided in the ``lucid`` class. .. image:: ../../../images/multi_layer_quad_mesh_pcb.png :align: center :width: 800 :alt: Generic PCB geometry. The resulting mesh with three layers per solid looks like this: .. image:: ../../../images/multi_layer_quad_mesh_pcb_3.png :align: center :width: 500 :alt: Generic PCB geometry meshed. .. image:: ../../../images/multi_layer_quad_mesh_pcb_2.png :align: center :width: 500 :alt: Generic PCB geometry meshed, zoom in. Procedure ~~~~~~~~~~ #. Import the fundamental libraries that are necessary to run the script. #. Launch an Ansys Prime Server instance. #. Instantiate the meshing utilities from the ``lucid`` class. #. Define the base mesh size and number of layers along the sweep direction. #. Import the CAD geometry. #. Define the edge sizing along the sweep direction using existing edge named selections. #. Define the parameters for the volume sweeper. #. Set up, generate, and mesh the base face. #. Stack the base face along the sweep direction. #. Set up the zone naming before the mesh output. #. Write a CAS file for use in the Fluent solver. #. Exit the PyPrimeMesh session. .. GENERATED FROM PYTHON SOURCE LINES 84-88 Import all necessary modules ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Notice that you must install the PyVista library to be able to run the visualization tools included in this script. .. GENERATED FROM PYTHON SOURCE LINES 88-95 .. code-block:: Python import os import tempfile import ansys.meshing.prime as prime from ansys.meshing.prime.graphics import PrimePlotter .. GENERATED FROM PYTHON SOURCE LINES 96-101 Launch Prime server and instantiate the ``lucid`` class ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Launch an instance of Ansys Prime Server. Connect the PyPrimeMesh client and get the model. Instantiate meshing utilities from the ``lucid`` class. .. GENERATED FROM PYTHON SOURCE LINES 101-106 .. code-block:: Python prime_client = prime.launch_prime() model = prime_client.model mesh_util = prime.lucid.Mesh(model=model) .. GENERATED FROM PYTHON SOURCE LINES 107-115 Define CAD file and mesh settings ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Define the number of layers per solid. Define the size in mm of the quad-dominant mesh on the base size. Define the path to the CAD file to mesh. Download the example CAD file using the ``prime.examples`` function. Otherwise, write the path to the desired CAD file on your machine. Supported file types are SCDOC, DSCO, and PMDB. .. GENERATED FROM PYTHON SOURCE LINES 115-124 .. code-block:: Python # cad_file='/path/to/any/cad/file.dsco' cad_file = prime.examples.download_multi_layer_quad_mesh_pcb_pmdat() layers_per_solid = 4 # number of hexa mesh layers in each solid base_face_size = 0.5 # surface mesh size in mm on the base face # Chose whether to display the CAD/mesh at every stage display_intermediate_steps = True # Use True/False .. GENERATED FROM PYTHON SOURCE LINES 125-129 Import geometry ~~~~~~~~~~~~~~~ Import the geometry into Prime server. Use the Workbench ``CadReaderRoute`` to ensure that the shared topology is kept. .. GENERATED FROM PYTHON SOURCE LINES 129-136 .. code-block:: Python mesh_util.read(file_name=cad_file) # Use the following command to open CAD files of these types: SCDOC, DSCO, and PMDB. # mesh_util.read( # file_name = cad_file, # cad_reader_route = prime.CadReaderRoute.WORKBENCH) .. GENERATED FROM PYTHON SOURCE LINES 137-139 Display the imported CAD in a PyVista window ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. GENERATED FROM PYTHON SOURCE LINES 139-144 .. code-block:: Python if display_intermediate_steps: display = PrimePlotter() display.plot(model) display.show() .. tab-set:: .. tab-item:: Static Scene .. image-sg:: /examples/gallery_examples/gallery/images/sphx_glr_09_multi_layer_quad_mesh_pcb_001.png :alt: 09 multi layer quad mesh pcb :srcset: /examples/gallery_examples/gallery/images/sphx_glr_09_multi_layer_quad_mesh_pcb_001.png :class: sphx-glr-single-img .. tab-item:: Interactive Scene .. offlineviewer:: /home/runner/work/pyprimemesh/pyprimemesh/doc/source/examples/gallery_examples/gallery/images/sphx_glr_09_multi_layer_quad_mesh_pcb_001.vtksz .. GENERATED FROM PYTHON SOURCE LINES 145-152 Define edge sizing constraints ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Set generic global sizing from 0.002mm to 2mm. Extract the the edge's length from the named selections, such as "edge_1_0.50_mm" (extract 0.5 mm length) or "edge_23_0.27_mm" (extract 0.27mm length). On each edge, assign a size equal to the edge's length divided by the predefined number of layers per solid. .. GENERATED FROM PYTHON SOURCE LINES 152-181 .. code-block:: Python # Set generic global sizing from 0.002mm to 2mm. model.set_global_sizing_params(prime.GlobalSizingParams(model, min=0.002, max=2.0)) ids = [] # collect the imported geometry part = model.parts[0] for label in part.get_labels(): # Check whether the named selection's name starts with the string "edge" if label.startswith('edge'): # Extract the edge's length, splitting its name at every "_" string # Collect the second to last number length = float(label.split("_")[-2]) # get 0.27 from "edge_23_0.27_mm" # Initialize a constant-size mesh control (SOFT) soft_size_control = model.control_data.create_size_control(prime.SizingType.SOFT) # Assign a mesh size equal to the edge's length/number of mesh layers soft_size_params = prime.SoftSizingParams(model=model, max=length / layers_per_solid) # Finalize the creation of mesh sizing soft_size_control.set_soft_sizing_params(soft_size_params) soft_size_scope = prime.ScopeDefinition( model, part_expression=part.name, entity_type=prime.ScopeEntity.FACEANDEDGEZONELETS, label_expression=label + "*", ) soft_size_control.set_scope(soft_size_scope) soft_size_control.set_suggested_name(label) # Append the id of the edge sizing to the edge sizings' ids' list ids.append(soft_size_control.id) .. GENERATED FROM PYTHON SOURCE LINES 182-189 Define controls for volume sweeper ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Set the sweep direction vector. Set up the geometric tolerances for lateral and stacking defeature. Select the sweep direction as the z axis (0,0,1). Append the IDs of the soft local sizings that have been previously defined on the edges. .. GENERATED FROM PYTHON SOURCE LINES 189-202 .. code-block:: Python # Instantiate the volume sweeper sweeper = prime.VolumeSweeper(model) # Define the parameters for stacker stacker_params = prime.MeshStackerParams( model=model, direction=[0, 0, 1], # define the sweep direction for the mesh delete_base=True, # delete the base face in the end of stacker lateral_defeature_tolerance=0.001, stacking_defeature_tolerance=0.001, size_control_ids=ids, ) # list of control IDs to be respected by the stacker .. GENERATED FROM PYTHON SOURCE LINES 203-210 Set up, generate, and mesh the base face ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Create a soft sizing control. Assign the previously defined ``base_face_size`` function to the soft sizing. Create the base face. Mesh the base face. Display the base face. .. GENERATED FROM PYTHON SOURCE LINES 210-241 .. code-block:: Python # Set up the necessary parameters for the generation of the base face. soft_size_control = model.control_data.create_size_control(prime.SizingType.SOFT) soft_size_params = prime.SoftSizingParams(model=model, max=base_face_size) soft_size_control.set_soft_sizing_params(soft_size_params) soft_size_scope = prime.ScopeDefinition( model, part_expression=part.name, entity_type=prime.ScopeEntity.FACEANDEDGEZONELETS ) soft_size_control.set_scope(soft_size_scope) soft_size_control.set_suggested_name("b_f_size") # Create the base face, appending the the stacker mesh parameters. createbase_results = sweeper.create_base_face( part_id=model.get_part_by_name(part.name).id, topo_volume_ids=model.get_part_by_name(part.name).get_topo_volumes(), params=stacker_params, ) base_faces = createbase_results.base_face_ids model.get_part_by_name(part.name).add_labels_on_topo_entities(["base_faces"], base_faces) scope = prime.ScopeDefinition(model=model, label_expression="base_faces") base_scope = prime.lucid.SurfaceScope( entity_expression="base_faces", part_expression=part.name, scope_evaluation_type=prime.ScopeEvaluationType.LABELS, ) # Generate the quad-dominant surface mesh on the base face. mesh_util_controls = mesh_util.surface_mesh_with_size_controls( size_control_names="b_f_size", scope=base_scope, generate_quads=True ) .. GENERATED FROM PYTHON SOURCE LINES 242-244 Display the meshed base face in a PyVista window ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. GENERATED FROM PYTHON SOURCE LINES 244-250 .. code-block:: Python if display_intermediate_steps: display = PrimePlotter() display.plot(model, update=True) display.show() .. tab-set:: .. tab-item:: Static Scene .. image-sg:: /examples/gallery_examples/gallery/images/sphx_glr_09_multi_layer_quad_mesh_pcb_002.png :alt: 09 multi layer quad mesh pcb :srcset: /examples/gallery_examples/gallery/images/sphx_glr_09_multi_layer_quad_mesh_pcb_002.png :class: sphx-glr-single-img .. tab-item:: Interactive Scene .. offlineviewer:: /home/runner/work/pyprimemesh/pyprimemesh/doc/source/examples/gallery_examples/gallery/images/sphx_glr_09_multi_layer_quad_mesh_pcb_002.vtksz .. GENERATED FROM PYTHON SOURCE LINES 251-257 Stack the base face using the volume sweeper ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Use the volume sweeper to stack the base face along the previously defined sweep direction. Include the previously defined stacker parameters. Display the final volume mesh. .. GENERATED FROM PYTHON SOURCE LINES 257-266 .. code-block:: Python # Use the ``stack_base_face`` function to generate the volume mesh stackbase_results = sweeper.stack_base_face( part_id=model.get_part_by_name(part.name).id, base_face_ids=base_faces, topo_volume_ids=model.get_part_by_name(part.name).get_topo_volumes(), params=stacker_params, ) .. GENERATED FROM PYTHON SOURCE LINES 267-269 Display the final PCB mesh in a PyVista window ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. GENERATED FROM PYTHON SOURCE LINES 269-274 .. code-block:: Python if display_intermediate_steps: display = PrimePlotter() display.plot(model, update=True) display.show() .. tab-set:: .. tab-item:: Static Scene .. image-sg:: /examples/gallery_examples/gallery/images/sphx_glr_09_multi_layer_quad_mesh_pcb_003.png :alt: 09 multi layer quad mesh pcb :srcset: /examples/gallery_examples/gallery/images/sphx_glr_09_multi_layer_quad_mesh_pcb_003.png :class: sphx-glr-single-img .. tab-item:: Interactive Scene .. offlineviewer:: /home/runner/work/pyprimemesh/pyprimemesh/doc/source/examples/gallery_examples/gallery/images/sphx_glr_09_multi_layer_quad_mesh_pcb_003.vtksz .. GENERATED FROM PYTHON SOURCE LINES 275-281 Set up the zone naming before the mesh output ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Delete the unnecessary topo entities. Name the walls of ``solid`` as ``wall_solid``. For example, if the solid's name is ``A``, then name the walls surrounding the solid ``wall_A``). Convert the labels to mesh zones. .. GENERATED FROM PYTHON SOURCE LINES 281-298 .. code-block:: Python # Define deletion parameters deletion_params = prime.DeleteTopoEntitiesParams( model, delete_geom_zonelets=True, delete_mesh_zonelets=False ) # Delete unnecessary geometrical entities. part.delete_topo_entities(deletion_params) # Rename the walls surrounding any volume of the mesh by appending the string # ``wall_`` to the solid's name. For example, if the solid is named ``my_solid``, then # name the walls surrounding the solid ``wall_my_solid``. for volume in part.get_volumes(): volume_zone_name = "wall_" + model.get_zone_name(part.get_volume_zone_of_volume(volume)) label_zonelets = part.get_face_zonelets_of_volumes([volume]) part.add_labels_on_zonelets([volume_zone_name], label_zonelets) # Convert labels into mesh zones to use in the solver. mesh_util_create_zones = mesh_util.create_zones_from_labels() .. GENERATED FROM PYTHON SOURCE LINES 299-302 Mesh output ~~~~~~~~~~~ Create a temporary folder and use it to output the mesh to a CAS file. .. GENERATED FROM PYTHON SOURCE LINES 302-311 .. code-block:: Python with tempfile.TemporaryDirectory() as temp_folder: mesh_file = os.path.join(temp_folder, 'multi_layer_quad_mesh_pcb.cas') mesh_util.write(mesh_file) assert os.path.exists(mesh_file) print("\nExported file:\n", mesh_file) # Otherwise, specify a path on your local machine: # mesh_util.write('local/path/to/your/mesh_file.cas') .. rst-class:: sphx-glr-script-out .. code-block:: none Exported file: /tmp/tmpmt8xozs2/multi_layer_quad_mesh_pcb.cas .. GENERATED FROM PYTHON SOURCE LINES 312-314 Exit PyPrimeMesh ~~~~~~~~~~~~~~~~ .. GENERATED FROM PYTHON SOURCE LINES 314-316 .. code-block:: Python prime_client.exit() .. rst-class:: sphx-glr-timing **Total running time of the script:** (1 minutes 41.888 seconds) .. _sphx_glr_download_examples_gallery_examples_gallery_09_multi_layer_quad_mesh_pcb.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: 09_multi_layer_quad_mesh_pcb.ipynb <09_multi_layer_quad_mesh_pcb.ipynb>` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: 09_multi_layer_quad_mesh_pcb.py <09_multi_layer_quad_mesh_pcb.py>` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_