• CFD, Fluid Flow, FEA, Heat/Mass Transfer

Solution Domain

Geometry or computational domain for CFD simulation requires a water tight geometry with simplification to handle the mesh creation process. Solution of computational domain refers to 2D or 3D geometry in which fluid flow and/or heat transfer phenomena need to be solved. This is known as "ZONES" in FLUENT, "REGIONS" in STAR-CCM+ and "DOMAIN" in CFX. These are "volumes surrounded by closed surfaces(called boundaries)" in 3D and "areas closed by edges or lines (called boundaries)" in 2D. It is the mesh and nodes generated to define and represent the physical space mathematically. No geometrical information is associated with the solution domain.


Defeaturing in ANSYS Discovery |:| Blender for Geometry Clean-up || Create Periodic Planes |:| Domain size reduction by sub-modeling ]=[ CAD Data Exchange [=] Parametric Geometry Creation [*] Few Recommendations for Parametric Modeling [=] Create Driving Dimension using Measurements from within the Pull Tool [*] Script to move objects defined by Named Selections

The geometry creation for CFD can be accomplished by either of the following two methods:

  • Create geometry in any CAD (Computer-Aided Design) software such as Unigraphics, Catia, Pro/E, Solidedge. The geometry information created so far is called to be in "Native CAD" format. This geometry should be translated to a Neutral format such as IGES, STEP, Parasolid. All Pre-processors available has build-in capacity to read (Import) CAD data in this format. Once the geometry is imported into the Pre-processor, defeature as per requirement.
  • The second approach is to create geometry directly into the pre-processor. All commercial pre-processors has basic built-in features to create Geometrical Entities. We strongly recommend this approach for following two cases:
    • 2D simulation
    • When geometry is axisymmetric. In this case, one needs to create the 2D cross-section first and then extrude it by rotation. In ANSYS FLUENT, in the axisymmetric model the boundary conditions should be such that the centerline (where the radius reduces to zero) is an axis type instead of a symmetry type. The axis should the z-axis. Thus, for all 2D simulations, FLUENT expects geometry to be in XY-plane.
  • One widely used term in numerical simulation is Topology. A precise explanation is provided by Georgios Balafas in his master's thesis for the Master of Science program in Computational Mechanics "Polyhedral Mesh Generation for CFD-Analysis of Complex Structures": The topology of a mesh is an abstraction of the geometric model, that provides unambiguous, shape independent information about the relation between the entities that form the mesh structure. To this end, a mesh database is used in order to store various-level attributes of entities of different dimensions. These typically include 0-D entities, referred to, in literature, as vertices or nodes, 1-D entities, referred to as edges, 2-D entities, referred to as faces or facets and 3-D entities, referred to as solids, volumes, regions or cells.
  • Few other definition taken from previous reference:
    • "A face is said to be classified on the boundary of the geometric model, when it is adjacent to only one solid, which means that the free side of the face forms an external boundary. In the opposite case, where a face is adjacent to two solids, it is classified in the interior of the geometric model."
    • Mesh edges inherit their classification by their adjacent faces. Specifically, when an edge has at least one adjacent face that is classified on a model's boundary surface, the edge is also classified on the same boundary. To be more precise, in a conforming non-manifold three-dimensional mesh, an edge will have either zero or at least 2 adjacent boundary faces, however detecting one of them can be considered enough to classify the edge on the boundary as well. Furthermore, when an edge's adjacent boundary faces are classified on different boundary surfaces of the model, this denotes the edge's classification on a model's boundary edge, where 2 of its boundary surfaces intersect.
    • It is, therefore, adequate to count the amount of different boundary identifiers that are assigned to the adjacent faces of an edge, in order to conclude whether this edge is internal (zero boundary identifiers), on a boundary surface (one identifier), on a boundary edge (2 identifiers), or is a non-manifold edge (> 2 identifiers).
    • Extending the aforementioned classification criteria for vertices, a mesh vertex is classified on a model's boundary surface, when at least one of its adjacent edges is also classified on a boundary surface. Additionally, when at least one of the adjacent edges of a vertex is classified on a model's boundary edge, then the vertex is also classified on the same boundary edge. Finally, when there exist at least two adjacent edges classified on two different model's boundary edges, the vertex is classified on a model's corner, formed at the intersection of the boundary edges. In other words, the classification of a vertex with respect to the model can be determined by counting the amount of different boundary identifiers assigned to the adjacent faces of the vertex.
    • Zero boundary identifiers denote an internal vertex, while vertices on a boundary surface have adjacent faces with a unique identifier. Nodes on model's boundary edges have adjacency relationships to faces of two boundary identifiers in total and vertices on a model's corner sum up with three adjacent boundary identifiers. Finally, when a vertex has adjacent faces classified to more than three different boundary surfaces, the vertex is non-manifold.
The creation, clean-up and defeaturing of a computational domain require good understanding of geometrical operations such as stitching, project edges, remove extra (iso) edges, suppress edges, faces and parts... Note that there are cases where multiple fillets (as high as 3) form corners of protrusions. Hence, there can be 5 lines separated by small gaps. Since, such fillets have smooth tangency, intermediate edges are not required. However, it is not always possible to suppress or delete these edges. One option is to let them as it is, turn off proximity between edges while importing geometry in FLUENT mesher. Re-mesh later based on area threshold or skewness values.

Other operations include: extract centrelines (to plot variation of pressure or temperature vs. position), create mid-planes (to create plots on a non-planar surface), save curve data into .csv file, create enclosure, merges faces, create body-of-influence (BOI) geometry, create Face of Influence (FOI) geometry, scale-up or down a body... ANSYS Discovery has option to create Curve Tables and Hole Tables (Curve Table in the Annotation group under Detail tab), the centreline of a tube can be generated using 'Extract' tool in Beam section under Prepare tab. Fill Surface: create surfaces from free edges of a hole in a facet sheet body, Sew Sheet bodies: combine or sew multiple facet bodies into a single body, Bridge surface: (similar to loft operation in some CAD tools) create a body between two sets of edges of existing facet bodies. Extruding surfaces and sketches directly up to any user defined Plane with the "Up to Plane" method. Keep or delete imprinted edges when uniting bodies.

Unite bodies

To create a point at the mass center of a solid: Select the body click on the 'Origin' button in the Create section of the Design tab to create a new coordinate system located at the center of mass. Use the origin of this coordinate system and click on the 'Point' button in the Create section of the Design tab to create a point.

Creation of post-processing planes: when computational domain is not aligned to coordinate axes or the flow path are curved and twisted that any section would result in multiple non-contiguous surfaces, it is strongly recommended to create post-processing planes during geometry creation and meshing process. These faces should be named with prefix 'post_' and set as internal type in meshing (so that boundary layers do not grow over them). Though most of the solvers and post-processors has option to import such surfaces in STL format and imprint on the mesh, it is time consuming and may result in interpolation error. The 'internal' zone created shall have faces and nodes aligned on it and the solution variables are directly available there to calculate derived parameters such as mass flow rate and pressure. In case of imprinted surfaces, the solution variables have to be interpolated from nearest nodes, face and cell centers.


Unit Systems

Every designer needs to work on length units and thus all CAD modeling program or tool have some built-in features for default units and ways to convert from one units to others. The following image describes options to select unit system in SCDM.

SCDM-Units

If a cylinder is created in SCDM while unit for 'Length' is chosen as 'mm', when the unit is changed to 'inch', the size automatically scaled by a factor of 25.4 and there is no change in appearance of the geometry in graphics window.

All tools dealign with virtual geometry and mesh generation has option to scale the model. As units are not mentioned at every numerical value, scaling changes the value as per units specified. For example, for a cylinder the tool may contain information 'mm' in header row and only numbers for diameter, length and other keypoints (nodes, vertices...). When user changes the units to 'm', those values has to be divided by 1000 while only the header gets changed from 'mm' to 'm'.


Parametric Modeling (Geometry Creation) within CFD Environment

For optimization studies, ANSYS Workbench offers options to make simulations in the order defined as DOE (Design of Experiment) table, each row termed as Design Point. ANSYS SpaceClaim and Discovery has option to parametrize the geometrical operations such as Pull, Move... which can be used to change the shape, size and location of bodies. Such activities are specially important in situations where periodicity and symmetry exist such as heat exchangers, fins, external aerodynamics.

Parametric Modeling in ANSYS SpaceClaim / Discovery: For all operations which can be parametrized, the symbol 'P' in SpaceClaim and icon within context-menu in Discovery appear to create a parameter. The value field of a parameter can contain basic formula such as 0.02 * 25.4 to convert a dimension from inch to 'mm'.

The Groups tab contains Named Selections, Driving Dimensions and Script Parameters. Driving dimensions can be Measurement, Ruler Dimension, Pattern Count... When a Pull operation is initiated, the option to make it parametric appears only after a value is entered (after pressing the space bar). Similarly, Ruler Dimension can be used to change the size as shown below in one of videos from Ozen Engineering.

Discovery parametric

The method to create parameters is different in ANSYS SpaceClaim and Discovery. The design parameters are called Driving Dimensions and associated values are known as Ruler Dimension. The steps to create Driving Dimensions in SCDM is explained through following animation (referenced from SpaceClaim Online Help).

"Driving dimensions are created when there is a dimension on screen or a dimension in the properties panel." For example, selecting the round (fillet) and then clicking Create Group in the 'Groups' panel creates a "driving dimension" instead of a "named selection" because the face selected is a round, which has a dimension property that can be controlled from the property panel. Similarly, a "round group" is created each time fill operation is used to create a round (fillet) and is saved in the Filled Rounds folder.

Note: clicking on a driving dimension created with 'Pull' operation automatically activates the 'Pull' operation ↴

Note that the GUI in the two videos are a bit old and in recent versions, Create Group has been replaced with Create NS and Create Parameter. When a dimension is showing and "Create Parameter" is clicked, it usually create a driving dimension with initial value appearing on the screen. The orientation of Move handle can be changed by using the Direction tool guide, holding Alt and selecting a reference object, or by dragging a ball on the axes of the Move handle. That is, Alt + click a point or line orients one of the axes of Move handle towards that point or along that line. Alt+click on a plane, the direction of movement is set perpendicular to the plane. Steps to create Driving Dimensions using Move operation ↴

The behaviour of the Move tool changes based on what is selected and direction of axes of move handle change based on the orientation on the screen. Press Ctrl to copy the object selected for movement and place it at the location at which user drags or dimensions the move. Video titled "Using Ansys SpaceClaim and Ansys Discovery for Parametric CAD Modeling" from KETIV Technologies gives good explanation of the methods described above. As per help.spaceclaim.com/2016.0.0/en/Content/Groups.htm: Group order is important because they are changed from top to bottom when the change is initiated in an external application.

Steps to create Move handle at 'Zero' initial value is explained below. The yellow centre sphere of Move handle turns into a blue cube when the Move handle is anchored.

SCDM-Param-Zero-Mean

Steps are
  1. Select face(s) or object(s) to be moved
  2. Press 'm' or click 'Move' icon under 'Edit' group in Ribbon bar
  3. Select anchor point or edge
  4. Select axis on the Move handle
  5. Press space bar on keyboard (0 will appear near Move handle origin)
  6. Click 'Enter' key (to accept '0' as initial value)
  7. Click on "+Create Parameter" icon in Group tab to create the Driving Dimension.

Move operation is very much similar to Pull operation though the behaviour of the Move tool changes based on what is selected. Though Pull allows operation in only one direction, Move allows operation in multiple directions. If an entire object, such as a solid, surface, or sketch is selected, 'Move' operation translates or rotates the object. If one side of a solid, surface, or sketch is selected, move operation shall enlarge or reduce the size of the object. If an object is moved into another object in the same component, the smaller object is merged into the larger one and receives the larger object's properties. Moving the apex of a cone changes the height, Anchor the Move tool to the outer face to scale the cone.

By default the 'Move' handle seems to be placed at the centroid of chosen objects (faces, edges...). However, there are cases when an axis was create using same set of objects, the location of origin of the axis and location or the origin of move handle were not coincident. In absence of clear documentations, following error may occur.

SCDM-Move-Centroid

The context-base menu is described below. Use the Anchor tool guide to set local origin of 'Move' handle.

SCDM-Move-Context-Menu

By default, the driving dimension to be created using 'Move' operation requires a reference object (face, edge, vertex...). Many a time the location of Move handle may not coincide the reference object - how can a driving parameter created with initial value of 0 unit? Refer the explanation above.

Create Driving Dimension using Measurements from within the Pull Tool: referenced from User Guide

  1. Enter the Pull tool and select an object(s) to pull
  2. Enter the Measure tool (shortcut is e) and measure any single object or measure between two objects
  3. Click the measurement result that will drive the Pull (hover over measurements output box to display a purple box)
  4. Once selected, that single measurement will display on screen with arrows pointing to either object chosen for measurement
  5. Click in the highlighted dimension box and open the Groups panel
  6. Click "+Create Parameter" and the measurement group gets created.
Note that this method does not ask to select a direction and hence unwanted geometrical change may occur if measurement directions are not aligned with axes of coordinate system.

SCDM-Move-Fulcrum

Select an object, then use the Anchor tool guide to select the face, edge, or vertex that will anchor the move. You can anchor the Move handle to a temporary object, such as the intersection between two axes by Alt+Shift+clicking the two objects. Select an object, then use the Fulcrum tool guide to move other objects around it.

From Workbench (V20) User Guide: "Negative dimension values can invert the direction vector of operations with which they are associated. This change is applied to the current and subsequent design point updates. As a result, when a Workbench input parameter is used as a driving dimension for a geometry, negative dimension values can result in unexpected geometric changes."


Geometry Fully or Partially Enclosed in a Fluid Domain

Solid-within-Enclosure

Sometimes a solid object or multiple solids need to be enclosed in a fluid volume fully or partially (may have periodic and/or symmetric faces). The fluid zone surrounding the solid(s) should not be a water-tight solid body - it can be a surface body with interfaces with solid boundaries removed. This way, only the common edges between the geometry representing fluid volume and those representing the solids need to be shared.

Straight-Length-Fillet

The image above describes the formula to estimate lengths when a fillet is applied on tapered edge (the common edge between tapered and straight faces). Be careful while measuring the distance between a plane or arc and an axis or edge - the result may not be what is expected to be measured.

It is not explicitly documented in SCDM user manual in which order the parameters get updated - however it is logical to assume that the parameters shall get updated in the order they are created / stored. And the parameters are stored in the order they are created and not in the order sorted by user say ascending alphabetically. It is better to define parameters with constant reference frame instead of taking reference from any other floating object.

ANSYS WB as in version 2024 does not allow to change the ID of parameters though GUI and they are stored in the order they are created. Parameter ID can be changed by editing the Workbench project file *.wbpj using a text editor. Search for all instances of a parameter which usually is named as P** where ** represents the sequence number (such as P1, P2, P13, P21...) and replace them by the new name (preferably keeping the naming convention same). If parameters have been used in expressions, renaming parameters should take care of keeping this dependency.

Few Recommendations for Parametric Modeling

  1. Keep all references to measure length with respect to fixed surfaces and/or edges (those which are not affected by geometrical changes
  2. While moving a round (fillet), use the edge of fillet on the side of straight face - in other words align the "direction of move" and "direction of measurement"
  3. Create parameters in group and order which does not contradict to subsequent constraints - note that if any parameter definition is missed for a shape, it will come later in the list (sequence of update) and may result in incorrect shape and size
  4. Keep testing the correctness of parametrization in small chunks (such as group of 10 driving dimensions) - this will help identify the driving dimension(s) causing failure in update of the geometry (create back-up after each successful check)
  5. Create a simple yet distinct naming convention for driving dimensions such p11_x_h where 1 refers to type 1, next 1 refers to item 1, x refers to direction, [h, w, b..] may refer to the variable names such as height, width, gap...
  6. In ANSYS SpaceClaim, you cannot change the order of driving dimensions - hence a careful planning is critical, especially all the dimensions required for a particular feature such as protrusions or cut-outs should be in consecutive sequence
  7. Create parameters responsible for changes in size first followed by parameters or ruler dimensions required for translation of objects
  8. Organize the variables in DOE table in the similar order (as per the expected sequence of update in CAD environment)
  9. Do not use default location of 'Move' handle which is near the centroid of the chosen objects, if shape changes the centroid will change and hence translation dimension need to account for this change in centroid position.

In general (for a single solid body and not assembly), the order of update of parameters or driving dimension should not matter. If the order of update affects the final shape and size of the body, recheck the input dimension - they might not be correct. For example, some update might have resulted in loss of feature (a face or edge) leading to missing reference for next update.

When a parameter is changed in SCDM, the geometry change is updated but the parameter set value does not update in Workbench parameter set. User the option Update Parameter in SpaceClaim under the 'Workbench' tab which will push the updated value to Parameter set.

Using an Excel Spreadsheet to Drive Dimensions

This utility is part of add-ins which can be activated using SpaceClaim Options > Add-ins > (Check the box) Excel Dimension Editor Add-in > Restart SpaceClaim.

SCDM-Excel-Add-on

As per SpaceClaim User Guide: "Values are applied sequentially, so order your groups in the sequence that you want to perform the operations." Reference: help.spaceclaim.com/dsm/ ... /t_driving_dimensions_excel.html

Driving Changes with Annotation Dimensions

3D annotation dimensions can be used to change design using the Pull and Move tools. Annotation dimensions can be used in combination with ruler dimensions. Dimension can be used for every element in design, from lines in sketches to faces of solids. In Discovery SpaceClaim, dimensions are not constraints rather tools for precise control during the creation or modification of a design. To save a dimension with the design, Ruler Dimension option can be used when pulling or moving.
Error: File has wrong dimensions (3) > this is usually reported in case 2D geometry is not in XY plane (which Fluent is expecting). By default SpaceClaim draws sketch in XZ plane which needs to be rotated to meet requirement for Fluent pre-processor.

As per innovationspace.ansys.com/ ... /driving-parameter-and-script-parameter:

# Get list of named selections and driving dimensions in Groups tab
dims_NS = Window.Groups.GetValue(Window.ActiveWindow)   
#
# 3-tuple type: value is index 1, type is index 2 
# Type = (Linear, Angular, Arc, Area, Diametric, Mass, Volume)
dims_NS[0].TryGetDimensionValue()    
dims_NS[0].SetDimensionValue(value)
A script to move objects defined by Named Selection is described below (not tested - generated by AI). Note that SCDM recording feature does not capture steps to create ruler dimensions. And hence the ruler dimensions cannot be accessed in Python script - changing ruler dimension is same as executing a move operation.
import SpaceClaim.Api.V242 as sc
from SpaceClaim.Api.V242 import Point, Direction, DesignPoint
#from SpaceClaim.Api.V242 import *
'''
User Inputs: Named Selections and Move Direction
object_to_move = Named selection for object(s) to move
move_dir_name  = Named selection of face/edge to get direction
ref_point_name = Named selection of a vertex or point
move_distance  = Distance to move in [mm]
'''
object_to_move = "ns_fillet_x"            
move_dir_name  = "ns_mmv_dir_1"      
ref_point_name = "ns_ref_pnt_1"
ns_move_anchor = "ns_anchor"
move_distance  = 50

target_selection = Selection.CreateByGroups(SelectionType.Primary, object_to_move)
move_direction = Selection.CreateByGroups(SelectionType.Primary, move_dir_name)
anchor = Selection.CreateByGroups(SelectionType.Primary, ns_move_anchor)
direction = Move.GetDirectionAlignedTo(target_selection, move_direction)
# or
direction = Move.GetDirectionAlignedTo(anchor, move_direction)
# or
direction = -Direction.DirZ
# or move by face normal
move_face = Selection.CreateByGroups(SelectionType.Primary, ns_move_face)
direction = Move.GetDirection(move_face)
#
options = MoveOptions()
'''
options.CreatePatterns = False
options.DetachFirst = False
options.MaintainOrientation = False
options.MaintainMirrorRelationships = True
options.MaintainConnectivity = True
options.MaintainOffsetRelationships = True
options.Copy = False
options.SnapAssociatedVertices = True
options.SubProportionalRadius = MM(0)
'''
result = Move.Translate(target_selection, direction, MM(5), options, Info1)

# Get direction vector from edge or planar face normal
direction_item = move_direction.Items[0]
if direction_item.ShapeType == sc.ShapeType.Edge:
  curve = direction_item.Geometry
  direction_vector = (curve.EndPoint - curve.StartPoint).Direction
elif direction_item.ShapeType == sc.ShapeType.Face:
  face = direction_item.Geometry
  direction_vector = face.Normal
else:
  raise Exception("Move Direction must be an edge or planar face.")

reference_point = Selection.CreateByGrousp(ref_point_name)
if reference_point and reference_point.Count > 0:
  ref_item = reference_point.Items[0]
  if hasattr(ref_item, 'Point'):
    ref_point = ref_item.Point
  else:
    ref_point = ref_item.Shape.Geometry.Center
else:
  ref_point = Point.Origin  # default to origin if not specified

move_vector = direction_vector * move_distance
transform = Transform.CreateTranslation(move_vector)

result = Move.Execute(target_selection, transform)
print(f"Moved '{object_to_move}' by {move_distance} along '{move_direction}'")

def get_named_selection(ns_name):
  select_ns = Selection.CreateByGroups(ns_name)
  if not select_ns or select_ns.Count == 0:
    raise Exception(f"Named Selection '{ns_name}' not found or empty.")
  return select_ns

# Create Driving Dimension as parameter and apply initial transform of 0 [unit]
axis_map = {
  "X": coordinate_system.XDirection,
  "Y": coordinate_system.YDirection,
  "Z": coordinate_system.ZDirection
}
if move_axis not in axis_map:
  raise Exception("Invalid move_axis. Choose from 'X', 'Y', or 'Z'.")
selected_axis = axis_map[move_axis]
end_point = ref_point + 1.0 * selected_axis

ruler = RulerDimension.Create(target_selection, ref_point, end_point)
ruler.Parameter.SetName(f"p11_{move_axis}_x1")
ruler.Parameter.IsIndependent = True

initial_transform = Transform.CreateTranslation(selected_axis * 0)
Move.Execute(target_selection, initial_transform)

Get summary of dimensions for edges and/or faces

ns_list = GetActiveWindow() .ActiveWindow .Groups
mea_dim = []
for ns in ns_list:
  if (ns.GetNames().Contains("msr")):
    ns_members = ns.Members
    mea_dim.append(ns_members[0].Shape.Length) # Output is in [m]
mea_dim_row = ','.join(mea_dim)
print(mean_dim_row)
From discuss.ansys.com under topic "Extract edge length and export information":
import os
import io
import json
file_path = os.path.join(r"D:\Projects", "edge_lengths.json")
bodies = GetRootPart().GetAllBodies()
body = bodies[0]
edge = body.Edges[0]
e_length = edge.Shape.Length
len_dict = { "edge length" : e_length }
with io.open(file_path, "w", encoding="utf8") as json_file:
   json.dump(len_dict, json_file, ensure_ascii=False)

Guidelines to Design Thermal Management System

Following considerations are recommended to design air-cooled and liquid-cooled systems:
  1. The available space and envelope such as inlet and outlet connectors, location of fans... should be as per component placement
  2. For gas (air) cooled systems:
    • The design approach with passive cooling (natural convection) and active cooling (forced convection) are different
    • Both may use heat spreader (heat sinks) and thermal interface material
    • In passive cooling, the orientation of the part and hence the orientation of heat spreader or heat sink should is along direction of gravity
    • For active cooling case, the location of fan should be inline with the heat sink and there should be diverging duct to control the swirl of the fans
  3. For liquid cooled systems:
    • First criteria is to meet the pressure drop requirement (maximum permissible pressure drop) for specified flow rate
    • The cooling channel should be in a curved or serpentine shape to cover larger surface area which also ensures continuous mixing of hot and cold fluid (no formation of thermal boundary layer)
    • The heat conducting face of heat generating devices (MOSFET, IC, Capacitors...) should be directly mounted on the heat sink or cooling channel plates as per the layout of the components
    • Ensure good contact between the heat generating parts and the cooling plate or heat spreader by using thermal grease or thermal interface material (TIM)
    • The sizing of the channels are iterative: for cooling channels with Aluminium and copper, the liquid (cooling medium) velocity is limited to 2 [m/s] or 5-8 [ft/s]* and for stainless steel the limit is 4 [m/s]. This is to avoid pitting (erosion) at higher liquid velocities. High water velocity in copper channels can strip the protective copper oxide layers and thus accelerate corrosion-erosion of the channels
    • Sometimes a minimum average velocity is also need to be met to avoid fouling and depositions on the channel walls
    • The minimum wall thickness is governed by burst pressure requirements. In terms of thermal performance, a lower wall thickness leads to better conductive heat transfer.
* An Evaluation of Enhanced Cooling Techniques for High-Heat-Load Absorber: S. Sharma, C. Doose, E. Rotela and A. Barcikowski - The Advanced Photon Source, Argonne National Laboratory, Argonne, IL. The recommendation as per Boyd Corporation with water as flowing medium is:
Material Recommended maximum velocity
Low Carbon Steel 10 ft/sec - 3.0 [m/s]
Stainless Steel 15 ft/sec - 4.5 [m/s]
Aluminum 06 ft/sec - 1.8 [m/s]
Copper 08 ft/sec - 2.4 [m/s]
90-10 Cupronickel 10 ft/sec - 3.0 [m/s]
70-30 Cupronickel 15 ft/sec - 4.5 [m/s]

Naming Convention of Boundaries and Cell Zones

In any practical application of CFD simulations, the computational domain may comprise of many cells zones (fluid and solid zones) and boundary zones (walls, inlets and outlets). The engineer responsible for pre-processing may not be the one who creates solver file and post-processes the results. The reviewer(s) of the mesh and simulation set-up will certainly be not the engineer who created them. In order to convey the domain information seamlessly, a naming convention should be adopted, it can be a generic system applicable for large number of projects or a specific system for particular simulation set-up. An example is outlined below with following default setting: Newtonian, stationary, adiabatic, smooth boundaries or zones can be named arbitrarily though it is recommended to chose names and identifiers meaningfully.
  1. Inlet(s) and outlet(s) should be named as b_inlet_id, b_outlet_id where 'id' stands for identifier.
  2. Walls with boundary conditions (other than adiabatic): w_tpr_id, w_hfx_id, w_htc_id, w_rot_id w_mov_id, w_rgh_id, w_s2s_id where 'rgh' stands for rough walls, s2s stands for coupled solid walls.
  3. Cell zones: fld_air_id, fld_wtr_id, fld_oil_id, fld_nnw_id, fld_rot_id, por_mom_id, por_thm_id, sld_alm_id, sld_stl_id, sld_src_id ... where 'nnw' stands for non-Newtonian fluids, 'src' stands for solid zones with heat source and/or sink and 'por' stands for porous (fluid) zones.
  4. Internal planes: int_f2f_id, int_baf_id ... where 'baf' stands for thin walls or baffles.
  5. Non-conformal interfaces: if_f2f_id, if_s2s_id, if_sta_rot_id, if_por_fld_id, if_por_por_id where 'sta' stands for 'stationary' zones and 'por' stands for 'porous' zones.
  6. All boundaries with no special setting or conditions to be applied on them can be named as 'b_def_id' or dumy-id1, dumy-id2 or empt-id1, empt-id2 or fblk-id1, fblk-id2 where dumy stands for dummy, empt for empty and fblk for flow-blockers. This is especially important while dealing with assemblies with large number of solids and fluid zones.

DOMAIN SIZE REDUCTION THROUGH SIMILARITY: In order to results of the model to apply to the prototype, strict similarity rules must be followed.

A convenient frame of reference must be defined that applies to both model and prototype and corresponding locations must be defined using dimensionless ratios (for a sphere for example, angle on its surface, longitude and latitude lines). Thus, there exist similar conditions for corresponding points on both model and prototype. That is, the drag coefficient at a particular point on the sphere applies to both model and prototype.

The designer must follow, then geometric similarity (model and prototype), kinematic similarity (velocity vector direction is similar for both model and prototype), dynamic similarity (force vector direction is similar for both model and prototype), thermal similarity (heat fluxes)...

Note that similarity principles cannot be applied for all application without loss of accuracy. For example, to reduce size of an axial flow fan with shroud, either for numerical or experimental investigation, their is no thumb rule to account for blade-tip and shroud clearance. Hence, the designer has to establish his own "quality standards and acceptance criteria" to address this limitation


Domain size reduction by sub-modelling

Leakage Flow

A simple duct flow simulation can be carried out to find out pressure drop vs. flow rate curve or even hand calculations based on empirical data can be used to find out loss coefficient for the outlet-vent. Note that sudden contraction loss coefficient needs to be added to the value obtained based on simple channel flow between parallel plates.

Domain size reduction by axi-symmetry

Axi-symmetry

The computational domain can be a quarter symmetry, any other sector angle or even 2D plane around axis of the tank.

Defeaturing in ANSYS Discovery

The pre-processing activities require geometry simplifications (defeaturing) and ANSYS SpaceClaim has some powerful non-parametric features. One of them is the 'Pull' option (short-cut 'p') which is equivalent to 'sweep' or 'extrude' operation. By default, pull direction is tangent to the selected edge or perpendicular to the selected face. A direction can be chosen or pulled (sweep) along a curve. Selection: all holes equal to selected radius, all holes of same radius in same face, all holes of radius equal or smaller than select radius. Blend (b): create surface by two lines (it is equivalent to 'loft' operation in some CAD programs). Fill (f): create surface from a closed loop of curves. Move (m): the 'origin' option is to select the reference point on the source object.

Step-by-Step for Geometry Defeaturing and Simplifications (ANSYS Spaceclaim)

Step-1:

Split the large assemblies into smaller (if possible, geometrically less-dependent) domain. This helps avoid large memory requirement and further geometry clean-up operations as well.

Step-2: Re-group and rename the data

The geometry in CAD environment is created keeping in mind the physical construction and assembly sequences. This is not important in mesh generation. It is better to re-group the geometrical (CAD) entities in terms of expected boundary definition. This makes it easy to operate on a smaller section of the entire domain. The selection, hide/unhide and operations such as imprint/ interference become faster.

Step-3:

Further segregate the geometry into 'Solids' and 'Surfaces'. This helps chose operations appropriate for the respective category. Such as fillet removal, split, booleans and extrude (pull) is easy on solids.

Step-4:

Convert the solids with thin wall thickness into solids with no internal wall and void. For example, a beam with fillets and internal wall.

Convert a hollow beam to solid beam

Step-5:

Before removing the wall thickness, use the operations appropriate for solids such as Booleans like unite, intersect... to make sure the once converted to surface, no further operations such as extend /intersection is needed to remove the gaps / connect the surfaces. Note that this method is no recommended for FEA simulation. in CFD the blockage of flow is important where as in FEA the location of centroid is important.

solid To Surface MidSurface Extraction

Step-5:

ANSYS Spaceclaim is a CAD-type pre-processor and works better on solids. CFD volume extraction is a analogous to 'negative' of visible solid volumes. Instead of deleted the unwanted surfaces one-by-one, it is recommended and worth trying to create a "bounding box" enclosing the geometry and use a booleaan to subtract the solids from the 'bounding' box. The resultant negative volume of fluid domain is easy to operate and remove the protrusions generated due to gaps in original (input) geometry.

SpaceClaim has versatile feature called Pull operation which can be used to extrude faces and edges, create fillets and chamfer and remove materials. Tangent and Natural (curvature continuous) extension can be toggled when dragging the end of a curve. To drag the extension Tangent to the curve, press and hold Ctrl prior to dragging. Press 'Ctrl' and drag to 'Pull' the curve end tangent to the curve. Surface edges can be Pulled normal to their neighbouring face. Press the Ctrl key when you begin the Pull. Press Ctrl and drag to Pull the edge tangent to the surface. Pulling a face with its edges selected extrudes the face without influence from neighbouring faces. Pulling a conical face "Up To" a parallel cylindrical face replaces the cone with the cylinder if the axes are close together. Otherwise, the conical face is replaced with a cylindrical face that is coaxial to the cone and has the same radius as the cylinder.


Tips and Tricks:

Definition: gaps in the plane of a surface is called lateral (horizontal) gaps and gaps in the direction of area normal is called the transverse (vertical) gap.

If you are dealing with large surfaces with small (transverse) gaps (say < 1% of the biggest geometry or say 1-5 [mm] which you can neglect), follow these steps:

  • Create a plane and/or planar surface encompassing the entire geometry which defines the best possible horizontal plane for the lower bound of the geometry.
  • Extend (using 'extrude', 'sweep' or 'pull' tool) by amount which covers (fills) all the unevenness (transverse gaps) in the geometry.
  • Split the bodies (solid volumes and surfaces) as per appropriate tool. E.g. in ANSYS SpaceClaim, "Split Body" can be used for both solid and surface bodies. 'Split' tool can be used for surfaces only.
  • This process will remove the 'local' details such as 'openings', small surfaces or patches for named selection... Project the curves from original geometry as needed and then split the bigger surfaces created during previous operations.
  • Delete the unwanted extensions created due to 'extend' and 'trim / split' operations.
  • Repeat the process for other bodies in the assembly.
  • Repeat the process for the upper and left / right bounds of the geometry. Though, once the lower and upper bounds are flattened (made coplanar), the 'blend' and 'fill' operation can be used to fill any lateral gaps between vertical edges and surfaces.

Fill operation: selecting many contiguous (connected) surfaces for fill operation does not work. However, selecting just one surface out of many makes the 'fill' tool act nicely. If 'fill' operation does not work while removing fillets and rounds, use Delete Rounds under Prepare > Remove > Rounds. Many a times, the sequence of fill operation determines the success of operation especially when fillets of different radii are connected in a loop. One need to visualize that the deletion of a fillet or blend should result in valid geometry.

Do not 'stitch' the geometry body and surfaces until you are done with all necessary clean-up and simplifications.

'Imprint' and 'Interference' operations do not make intended change in on go. Continue the operation till you get a message "No problem areas were fixed".

In ANSYS SpaceClaim, sometimes 'pull to' operation does not work. However, you can manually 'pull' or 'extend' the edges to or beyond the desired target edge. Hence, extend the edges manually and split them later to have a common boundary. Another option is to copy the surface(s) into a new model file and then do pull / fill / trim operations. Once desired shape is achieved, copy-paste the new geometry or shape back into main assembly.


assembly Gaps

One of the tedious and time-consuming work (which cannot be automated most of the time) is the fill small assembly gaps (especially in case of surfaces designed for aesthetic purposes). Such parts and surfaces tend to have high 3D curvature and multi-radii bends / fillets that cannot be easily removed. The blend, fill and pull operations on the two sides of such gaps tend to fail very often. The issue gets further complicated because the gaps are between two valid solids (there are no free edges) and hence any feature to find and fill gaps shall not work. As suggested above, the one option is to copy the surface(s) into a new model file and then do pull / fill / trim operations. Once desired filler surfaces are created, copy-paste the new geometry or shape into main assembly.

Sometimes, the edges of the surfaces forming the gaps are short and split into many segments. Most of the geometry defeaturing programs have option to Fit Curves. However, this operation may not work if curves are already associated with surface. In ANSYS SpaceClaim, Patch Fill is another option. First click on Fill Ribbon tool without selecting any geometry. Under the options, the default is Extend Fill. Change the option to Patch Fill. If any geometry was previously selected, it would have extended fill.


Split Geometry for Meshing

Many a times, it is a necessity to split the geometry appropriately into multiple volumes especially when this sections are present. Such splits are required to create extrudable or sweepable sections to generate either full hexahedral mesh or use thin sweeping method to generate all prism elements in narrow gaps. Splitting a body with plane is straightforward though the options to split a (solid) body with a curved plane (surface) is more frequently needed. ANSYS Discovery provides Combine operation to split solids using other solids or surfaces. In the image below where two cylinders are merged, a full cylindrical surface needs to be created (say for the vertical cylinder). This surface can be used to split the two cylinders into separate bodies.

Cylinders Merged

ANSYS Discovery has option to save all the components into separate files. Select the components, right-click and chose Convert to External. The icon for the component in the Structure tree changes to indicate 'external'. A batch converter converter.exe located in the install directory of Discovery can be used to convert files to other formats.

If the bodies are stored without components, directly under root components, select the bodies which needs to be saved in separate files, right click and chose "Move Each to A Component". This will move each body in separate components and the steps mentioned earlier can now be used to save them into separate files. Discovery has different type of components: internal, external, dependent and independent.


How to compare two geometry when external appearance look similar? One way is to check the surface area - the one with higher value is expected to have bigger cross-section and lengths. This can be further confirmed by comparing the volumes of the two geometries.


Blender Tool for Geometry Clean-up

Blender is not a CAD modelling program. For example, there is no concept of solids even if it is enclosed from all sides by faces, the concept of Boolean (add, subtract...) in Blender is not same as standard 3D CAD tools. Note that you can extrude a face and the operation is named as Solidify. Since Blender works on tessellated geometries, they are 'hollow' or "empty inside" by definition. The attributes such as mass or matter inside an object, centre of gravity... cannot be assigned to objects in Blender.

Other products offering similar features are Maya 3D and Houdini. From the website of Autodesk: "What is Maya? Maya is professional 3D software for creating realistic characters and blockbuster-worthy effects. Bring believable characters to life with engaging animation tools. Shape 3D objects and scenes with intuitive modelling tools. Create realistic effects – from explosions to cloth simulation." From the official page of Houdini: "Houdini is built from the ground up to be a procedural system that empowers artists to work freely, create multiple iterations and rapidly share workflows with colleagues. In Houdini, every action is stored in a node. These nodes are then “wired” into networks which define a “recipe” that can be tweaked to refine the outcome then repeated to create similar yet unique results. The ability for nodes to be saved and to pass information, in the form of attributes, down the chain is what gives Houdini its procedural nature."

GUI of Blender

Like many feature rich applications, the interface of Blender is a bit intimidating (complex and lost in ocean type) when you open it the first time. Understaing the GUI layout and context based sub-menu is key to get started.Blender General Preferences

Blender-Basic-GUI-2

Blender Input Preferences

Blender-Basic-GUI-3

"The Decimate Geometry tool allows you to reduce the vertex/face count of a mesh with minimal shape changes." Delete Loose: removes disconnected vertices and edges (optionally faces). Merge by Distance is a useful tool to simplify a mesh by merging the selected vertices that are closer than a specified distance to each other.

Blender Selection Transform

Select More/Less: More - Ctrl-Numpad Plus = Expands the selection to the adjacent elements of the selection type. Less - Ctrl-Numpad Minus = Contracts the selection from the adjacent elements of the selection type. Next Active - Shift-Ctrl-Numpad Plus: This uses selection history to select the next vertex, edge, or face based on surrounding topology. Previous Active - Shift-Ctrl-Numpad Minus: Select previous just removes the last selected element. Select Linked: Selects all components that are connected to the current selection.

Blender Operations on Vertices and Edges

Grid Fill: similar to Blend or Loft operation. Beautify Faces on selected faces rearranges triangles to obtain more 'balanced' ones (i.e. less long thin triangles that is triangles with lower aspect ratio). Solidify Faces is equivalent to Extrude or Pull operation. Limited Dissolve: Simplifies mesh by dissolving vertices and edges separating flat regions.

Blender Limited Dissolve

Change view to wireframe mode, select entities (say faces) based on similar attributes (area, perimeter, co-planar, normal...). The options for "Select Similar" changes based on selection of vertex, edge or face. All free edges can be selected by selecting one such (free) edge, and then Select: Select Similar: Amount of Faces around an Edge. If needed, these free edges can be sewed by fill operation.

Blender Select Similar

Collapse edges (merge vertices)

Blender Collapse Edges

Fix for Viewport Clipping
Also known as object cut-off issue, zooming in to inspect texture or mesh details in 3D view clips faces partially like a clipping mask not showing the full model. Click on the small left arrow (< sign) on the top right near XYZ-triad to open the following pane.

Blender Viewport Clipping Fix

Drag the left edge of pane towards right to close the pane which displays options for tabs Item, Tool and View.

Some challenges dealign with tessellated geometries are removing fillets and chamfers from imported say STL file, deleting coincident surfaces (common boundaries of two closed volumes), removing proximities at sharp corners and point contacts such as a tire contacting flat ground.

ANSYS Discovery (known as SpaceClaim and DesignSpark) has on option called Vectorize Image that creates curves around colored areas in images. This can be used to create a 2D domain from images. A colour convention can be use to define domain and material types (solid, fluid, insulator...).


Curves
A curve or segment of a curve is defined as collection of points whose coordinates are specified as continuous ONE-parameter and single-valued mathematical functions. In Cartesian coordinate system, it can be expressed as x = f(u), y = g(u) and z = h(u) where f, g and h are the single valued mathematical functions. 'u' is known as parametric variable and it is very often (and necessarily) constrained to the interval [0 1]. The curves are said to be point-bounded as it has two definite end points.

Linear parametric equation of curves: x = a + b.u, y = m + n.u, z = p + q.u where a, b, m, n, p and q are constants. The curves starts at p(u=0) = [a m p] and ends as [(a + b) (m + n) (p + q)] with direction cosines proportional to b, n and q.

Cubical parabola: x = a.u, y = b.u2, z = c.u3 where a, b and c are constants.

Left-handed circular helix: Also known as machine screw, the curves are described as x = r.cos(u), y = r.sin(u), z = p.u where r and p are constants. It is the locus (path) of a point that revolves around the z-axis at radius r and moves parallel to the z-axis at a rate proportional to the angle of revolution 'u' (known as pitch of the helix). Note that if p < 0 then it is a right-handed screw (helix).

All the 3 examples above demonstrate the versatility of parametric representation of a curve. However, we need to always have a independent variable (u or θ) as parameter. Even, x or y or z themselves can be a parameter so that x=f(x), y=g(x) and z=h(x). Similarly, the surfaces can be represented parametrically. This is the reason the 3D CAD geometry in SolidWorks, Unigraphics, Creo, Inventor, FreeCAD... are called parametric models and the method is called parametric modelling.

Algebraic Form of a Parametric Cubic (PC) Curve: Following 3 polynomials are required to define any curve segment of a PC curve:

x(u) = a0 + a1u + a2u2 + a3u3

y(u) = b0 + b1u + b2u2 + b3u3

z(u) = c0 + c1u + c2u2 + c3u3

The unique set of 12 constant coefficients are known as algebraic coefficients and determines the size, shape and position of the curve in space.

Geometric Form of a Parametric Cubic (PC) Curve: Algebraic coefficients do not lend much flexibility to control the shape of a curve in modelling situations as they do not account for conditions as its ends points or boundaries. When a curve is described based on its conditions as the ends (such as end point coordinates, tangents, curvature, torsion...), it is called geometric form of the curve.

geometric Cubic Curve

Finally, p(u) = (2u3 - 3 u2 + 1) p(0) + (-2u3 + 3u2) p(1) + (u3 - 2u2 + u) p'(0) + (u3 - u2) p'(1).
STEP/IGES
STEP (or STP) and IGES (or IGS) are two widely used neutral file format. IGES format was developed in 1980 by US Air Force in collaboration with Boeing, GE and Xerox. STEP format came into existence in 1984 as ISO standard 10303-21. Both these standards are plain text formats that use pre-defined special purpose syntax. For example, entity names in STEP format consists of digits preceded by '#'. /* ... */ defines comment. STEP format does not maintain features such as fillets, chamfers... as separate geometrical entities.

Create Periodic Planes

The easiest option is to cut the geometry with two planes inclined at desired sector angle and passing through the axis of rotation. This option any cut through the blades (rotating as well as stationary) through the domain shall still remain periodic by definition.

Periodic-section type 1

Another approach is to draw a plane passing between two adjacent blades, the plane need not pass through exactly middle point of the leading edges. Create another plane inclined to the first plane at required sector angle. Split the geometry by these planes.

Periodic-section type 2

The following method is similar to previous one except 5 to 8 planes may be required to split the geometry into axial and tangential directions.

Periodic-section type 3


CAD Data Exchange

STEP format is widely used in data exchange between CAD and numerical (FEA / CFD) simulations. It has many flavours known as AP: Application Protocol. Meta data such as surface names are included when using the STEP AP214. Most of the CAD programs including Siemens NX do not include surface names in a STEP (AP 242) export by default but they do have option to make the surface names included while using AP 214 of STEP format.

Similarly, to define 'names' in PTC Creo, the design can use: File > Prepare > Open Model Properties, then select 'Names' in the model properties dialogue. Then select faces by clicking > enter a name in the dialogue box opened in previous step. During CAD export to STEP format with default settings, the 'names' defined earlier do not get stored in the file. Change the export setup through File > Options > Configuration Editor > intf_out_assign_names > set it to 'user_name'.


Sample Scripts from Public Domains

ClearAll() 
# Open Project
File.Open(r"E:\Sctipts\Bracket.dsco")

# convert CAD files and save them in the same directory
import glob, os
os.chdir(r"E:\Scripts\")
for file in glob.glob("*.stp"):
  File.ResetProject()
  File.Open(os.path.join(os.getcwd(), file), ImportOptions.Create())
  File.SaveAs(os.path.join(os.getcwd(), file[:-4]+".igs"))

#run Discovery script in batch mode
"C:\Program Files\Ansys Inc\v221\Discovery\Discovery.exe" --run-script \
"E:\Scripts\pipe.scscript" --hidden --exit-after-script

# run Discovery script from WB project page
import os
myScriptGeometry = "E:\Scripts\pipe.scscript"
#SetScriptVersion(Version="22.1.217")
template1 = GetTemplate(TemplateName="Geometry")
system1 = template1.CreateSystem()
geometry1 = system1.GetContainer(ComponentName="Geometry")
geometry1.Edit(IsDiscoveryGeometry=True)
geometry1.RunScript(ScriptFile=myScriptGeometry,GeometryContainer="Geometry",useAsMacro="false")
geometry1.Exit()

def createPlaneOriginNormal(origin = [0, 0, 0], normalDirection = [0, 0, 1]): 
  originPoint = Point.Create(origin[0], origin[1], origin[2]) 
  dirZ = Direction.Create(normalDirection[0], normalDirection[1], normalDirection[2])
  frame = Frame.Create(originPoint, dirZ) 
  plane = Plane.Create(frame) 
  return plane 

def getGroup(groupName):
  groups = GetActiveWindow().ActiveWindow.Groups
  for group in groups:
    if group.GetName() == groupName:
      return group
  return None

def getDimensionValue(group):
  tryGetDimensionResult =  group.TryGetDimensionValue()
  if tryGetDimensionResult[0]:
    return True, tryGetDimensionResult[1]
  else:
    return False, 0

def setDimensionValue(group, value):
  group.SetDimensionValue(value)

# Fill
selection = Face1
secondarySelection = Selection.Empty()
options = FillOptions()
result = Fill.Execute(selection, secondarySelection, options, FillMode.ThreeD, Info1)

# Thicken Faces
selection = FaceSelection.Create(Face0, Face1, Face2, Face3)
options = ThickenFaceOptions()
result = ThickenFaces.Execute(selection, Direction.Create(0.707, 0, 0.707), MM(-5), options)

# Create Rounds
selection = PowerSelection.Edges.ByLength(Edge1, 
    PowerSelectOptions(True), SearchCriteria.SizeComparison.Equal)
options = ConstantRoundOptions()
result = ConstantRound.Execute(selection, MM(2.5), options, Info1)

# Save Project As
File.SaveAs(r"E:\Scripts\U-Bracket.dsco")
          
# Create a block 
startPoint = Point.Create(MM(5), MM(5), MM(15)) 
endPoint = Point.Create(MM(20), MM(20), MM(20)) 
BlockBody.Create(startPoint, endPoint) 

# Create rectangles 
RectangularSurface.Create(MM(40), MM(5),Point.Origin) 
RectangularSurface.Create(MM(5), MM(40),Point.Origin) 

# Merge rectangles 
allSurfaceBodies = PowerSelection.Bodies.AllSurfaceBodies() 
result = Combine.Merge(allSurfaceBodies) 

# Create a plane and switch to sketch mode 
origin  = [MM(5), MM(5), MM(5)] 
plane = create_a_plane_from_origin_and_normal(origin) 
ViewHelper.SetSketchPlane(plane) 

# Sketch Spline 
points = List[Point2D]() 
points.Add(Point2D.Create(MM(0), MM(15))) 
points.Add(Point2D.Create(MM(5), MM(5))) 
points.Add(Point2D.Create(MM(15), MM(0))) 
result = SketchNurbs.CreateFrom2DPoints(False, points) 
splineCurve = result.CreatedCurves[0] 

# Switch to 3D mode 
mode = InteractionMode.Solid 
ViewHelper.SetViewMode(mode) 

# Extrude spline 
selection = Selection.Create(splineCurve) 
options = ExtrudeEdgeOptions() 
result = ExtrudeEdges.Execute(selection, Point.Origin, Direction.DirZ, MM(30), options) 
resultFace = result.CreatedFaces 

## Slice block by resultFace 
toolFaces = Selection.Create(resultFace) 
selection = PowerSelection.Bodies.AllSolidBodies() 
result = SplitBody.ByCutter(selection, toolFaces, True) 

# delete unncessary bodies 
referencePoint = Point.Create(MM(5), MM(5), MM(15)) 
for body in GetRootPart().GetAllBodies(): 
  if not body.Shape.ContainsPoint(referencePoint): 
    body.Delete()

# Extrude resulting surface body 
faceToExtrude = result.GetModified[IDesignFace]() 
faceToExtrudeSelection = Selection.Create(faceToExtrude) 
options = ExtrudeFaceOptions() 
options.ExtrudeType = ExtrudeType.Add 
result = ExtrudeFaces.Execute(faceToExtrudeSelection, MM(40), options) 

# Create the named selections 
Selection.Create(GetRootPart().Bodies).CreateAGroup("SolidBody") 
for face in GetRootPart().Bodies[0].Faces: 
  if (face.Shape.ContainsPoint(Point.Create(MM(2.5), 0, MM(2.5)))): 
    Selection.Create(face).CreateAGroup("Fixed support") 
  if (face.Shape.ContainsPoint(Point.Create(0, MM(2.5), MM(2.5)))): 
    Selection.Create(face).CreateAGroup("Pressure load") 

#How to Access Groups
groups = GetActiveWindow().ActiveWindow.Groups
for group in groups:
  print group.GetName()

#How to get all items of a Group/Named Selection
group = GetActiveWindow().ActiveWindow.Groups[0]
Group.Members
#or
Selection.CreateByGroups("Height").Items        
heightGroup = getGroup("Height")

tryGetDimensionResult =  heightGroup.TryGetDimensionValue()
print tryGetDimensionResult

topGroup = getGroup("Top")
tryGetDimensionResult =  topGroup.TryGetDimensionValue()
print tryGetDimensionResult

heightGroup = getGroup("Height")
success, height = getDimensionValue(heightGroup)

if success:
  print height

heightGroup.SetDimensionValue(MM(5))
 
if success:
  print height
  setDimensionValue(heightGroup, height + MM(4))  

#Using script parameter to create a surface
Test = Parameters.Test
print Test
RectangularSurface.Create(Test,Test,Point.Origin)

#Units of Script Parameters
Length = Parameters.Length
myUnits = UnitsHelper.GetDocumentUnits()
print ("Parameter - SI units: " + str(Parameters.Length))
print ("Parameter - local units (" + myUnits.LengthProperties.Type.ToString() \
  + "): " + str(Parameters.Length*myUnits.LengthFactor))

#Set radius2 to initial value minus radius1 divided by 3
r1Group = getGroup("radius1")
success, radius1 =  getDimensionValue(r1Group)
r2Group = getGroup("radius2")
success, radius2 =  getDimensionValue(r2Group)
if success:
  print radius2
  setDimensionValue(r2Group, radius2 - radius1/3) 
    
Objects, Selections and Named Selections
#Access Bodies: select bodies using part.Bodies 
Selection.Clear()
part = GetRootPart()
bodies = part.Bodies
selection = Selection.Create(bodies)
selection.SetActive()

#Access Bodies: select bodies using part.GetBodies()
part = GetRootPart()
bodies = part.GetBodies()
selection = Selection.Create(bodies)

#select bodies using part.GetBodies(“filter”)
part = GetRootPart()
bodies = part.GetBodies("_2")
selection = Selection.Create(bodies)

#listing bodies using part.GetAllBodies()
part = GetRootPart()
bodies = part.GetAllBodies()
for body in bodies:
  print body.GetName()
  
#Index of bodies
part = GetRootPart()
bodies = part.GetAllBodies()
for index,body in enumerate(bodies):
    print index,body.GetName()

# Access Components:
part = GetRootPart()
for component in part.Components:
    print component.GetName()

part = GetRootPart()
for component in part.GetAllComponents():
    print component.GetName()

# Access Coordinate System:
part = GetRootPart()
for coordinateSystem in part.CoordinateSystems:
    print coordinateSystem.GetName()

for coordinateSystem in part.Components[0].GetCoordinateSystems():
    print coordinateSystem.GetName()

for coordinateSystem in part.Components[0].GetAllCoordinateSystems():
    print coordinateSystem.GetName()
       
for coordinateSystem in part.GetDescendants[ICoordinateSystem]():
    print coordinateSystem.GetName()

# Access Datum Plane
part.DatumPlanes
part.Components[0].GetDatumPlanes()
part.Components[0].GetAllDatumPlanes()

# Access Datum Lines
part.DatumLines
part.Components[0].GetDatumLines()
part.Components[0].GetAllDatumLines()

# Access Datum Points
part.DatumPoints
part.Components[0].GetDatumPoints()
part.Components[0].GetAllDatumPoints()

# Getting Faces of body:
myBody = GetRootPart().Bodies[0]
for myFace in myBody.Faces:
    myGeometry = myFace.Shape.Geometry
    if isinstance(myGeometry, Cone):
        ColorHelper.SetColor(Selection.Create(myFace), ColorHelper.Azure)
    if isinstance(myGeometry, Plane):
        ColorHelper.SetColor(Selection.Create(myFace), ColorHelper.Olive)
    if isinstance(myGeometry, Cylinder):
        ColorHelper.SetColor(Selection.Create(myFace), ColorHelper.Violet)

# Getting Descendants
myBody = GetRootPart().Bodies[0]
myEgdes = myBody.GetDescendants[IDesignEdge]()
mySel = Selection.Create(myEgdes)
mySel.SetActive()

# Getting newly created entities:
myBody = GetRootPart().Bodies[0]
myEgdes = myBody.GetDescendants[IDesignEdge]()
mySel = Selection.Create(myEgdes)
myOptions = ConstantRoundOptions()
result = ConstantRound.Execute(mySel, MM(1), myOptions)
mySelection = Selection.Create(result.CreatedFaces)
ColorHelper.SetColor(mySelection, ColorHelper.Cyan)
cfaces = result.CreatedFaces
length_cfaces = len(cfaces)
MessageBox.Show("Number of Created Faces:" + str(length_cfaces))

# Getting Modified entities
myBody = GetRootPart().Bodies[0]
myEgdes = myBody.GetDescendants[IDesignEdge]()
mySel = Selection.Create(myEgdes)
myOptions = ConstantRoundOptions()
result = ConstantRound.Execute(mySel, MM(1), myOptions)
mySelection = Selection.Create(result.CreatedFaces)
ColorHelper.SetColor(mySelection, ColorHelper.Cyan)
mySelection = Selection.Create(result.GetModified[IDesignFace]())
ColorHelper.SetColor(mySelection, ColorHelper.Magenta)

# Operating on Object lists
myBodies = GetRootPart().GetAllBodies()
Selection.Create(myBodies).SetActive()
myBodies.Remove(GetRootPart().GetAllBodies()[1])
Selection.Create(myBodies).SetActive()
myBodies.Remove(GetRootPart().GetAllBodies()[2])
Selection.Create(myBodies).SetActive()
myBodies.Add(GetRootPart().GetAllBodies()[1])
Selection.Create(myBodies).SetActive()

# ---------------------Selecting entities--------------------------------------

mySel_0 = Selection.GetActive()
for body in mySel_0.GetItems[IDesignBody]():
    print body.GetName()
mySel_1 = Selection.CreateByNames("Cylinder")
mySel_1.SetActive()
Selection.Clear()
mySel_1.GetInverse().SetActive()

mySel_2 = Selection.CreateByGroups("Top")
mySel_2.SetActive()

mySel_3 = Selection.CreateByNames("Box")
mySel_3.AddToActive()

mySel_4 = Selection.SelectAll()
mySel_4.SetActive()

mySel_5 = mySel_4 - mySel_3
mySel_5.SetActive()

# gets the current selection from the active view
mySel_1 = Selection.GetActive() 

# creates inverted selection
mySel_2 = mySel_1.GetInverse() 	

# selects objects from this selection in active view
mySel_2.SetActive()   			

# Power Selection
seedSelection = Selection.CreateByNames("b07")
powSelection = PowerSelection.Bodies.ByVolume(seedSelection, 
PowerSelectOptions(True), 
SearchCriteria.SizeComparison.SmallerOrEqual)
powSelection.SetActive()

seedSelection = Selection.CreateByNames("b08")
powSelection = PowerSelection.Bodies.ByVolume(seedSelection, 
PowerSelectOptions(False), 
SearchCriteria.SizeComparison.SmallerOrEqual)
powSelection.SetActive()

# Power Selection – selecting other bodies
otherBodies=Selection.Create(GetRootPart().GetAllBodies())
options=PowerSelectOptions(False, otherBodies)
seed=Selection.Create(GetRootPart().GetAllBodies("b03"))
pSel=PowerSelection.Bodies.ByVolume(seed, options, \
  SearchCriteria.SizeComparison.LargerOrEqual)
pSel.SetActive()

otherBodies=Selection.Create(GetRootPart().GetBodies())
options=PowerSelectOptions(False, otherBodies)
seed=Selection.Create(GetRootPart().GetAllBodies("b04"))
pSel=PowerSelection.Bodies.ByVolume(seed, options, \
  SearchCriteria.SizeComparison.LargerOrEqual)
pSel.SetActive()

# Power Selection – selecting seed
options=PowerSelectOptions(True,None,True)
seed=Selection.Create(GetRootPart().GetAllBodies("b07"))
pSel=PowerSelection.Bodies.ByVolume(seed, options, \
  SearchCriteria.SizeComparison.SmallerOrEqual)
pSel.SetActive()

options=PowerSelectOptions(True,None,False)
seed=Selection.Create(GetRootPart().GetAllBodies("b07"))
pSel=PowerSelection.Bodies.ByVolume(seed, options, \
  SearchCriteria.SizeComparison.SmallerOrEqual)
pSel.SetActive()

# Multiple Objects Selection
b1 = GetRootPart().Bodies[0]
b2 = GetRootPart().Bodies[1]
b3 = GetRootPart().Bodies[2]
# Approach 1 
s1 = Selection.Create(b1, b2, b3)
# Approach 2
body_list = [b1, b2]
body_list.Add(b3)
s2 = Selection.Create(body_list)
# Approach 3
list = List[IDesignBody]()
list.Add(b1)
list.Add(b2)
list.Add(b3)
s3 = Selection.Create(list)
# Approach 4
s4 = Selection.Create(b1, b2)
s4 = s4 + Selection.Create(b3)
s4.SetActive()

# Mixed Selections
b1 = GetRootPart().Bodies[0]
b2 = GetRootPart().Bodies[1]
b3 = GetRootPart().Bodies[2]
f1 = b3.Faces[0]
f2 = b3.Faces[1]
# Approach 1
s1 = Selection.Create(b1, b2, f1, f2)
# Approach 2
b_list = [b1, b2]
f_list = [f1, f2]
s2 = Selection.Create(b_list + f_list)
s2.SetActive()

# Multiple objects selection
b1 = GetRootPart().Bodies[0]
b2 = GetRootPart().Bodies[1]
b3 = GetRootPart().Bodies[2]
f1 = b3.Faces[0]
f2 = b3.Faces[1]
b_list = [b1, b2]
f_list = [f1, f2]
sel1 = Selection.CreateByObjects([b1, f_list])
sel2 = Selection.CreateByObjects([b_list, f_list])
sel3 = Selection.Create(b1, f1, f2)
sel3.SetActive()

#Creating Named Selections
for face in GetRootPart().Bodies[0].Faces:
  myNS=NamedSelection.Create(Selection.Create(face),Selection())
  if isinstance(face.Shape.Geometry, Cylinder):
    myNS.CreatedNamedSelection.SetName("sideWall")
  elif face not in Selection.CreateByGroups("inlet").GetItems[IDesignFace]():
    myNS.CreatedNamedSelection.SetName("outlet")
  else:
    myNS.CreatedNamedSelection.Delete()

myNS=NamedSelection.Create(Selection.CreateByNames("cylinder"),Selection())
myNSName=myNS.CreatedNamedSelection.GetName()
NamedSelection.Rename(myNSName,"myCylinder")
Selection.Create(GetRootPart().Bodies[0]).CreateAGroup("myCyl")

part = GetRootPart()
for component in part.Components:
  bodies = component.GetAllBodies()
  selection = Selection.Create(bodies)
  selection.SetActive()
  # Move bodies to root component
  result = ComponentHelper.MoveBodiesToComponent(selection, part, False)
    
# Delete Empty Components
ComponentHelper.DeleteEmptyComponents(part)

Selection.Clear()
myBodies = List[IDesignBody]()
part = GetRootPart()
for body in part.GetAllBodies():
  if body.Shape.Volume <= 3e-07 :
    myBodies.Add(body)
Selection.Create(myBodies).SetActive()

myFilter=3e-7
for body in GetRootPart().GetAllBodies():
  if body not in GetRootPart().GetBodies():
    ComponentHelper.MoveBodiesToComponent(Selection.Create(body),\
    GetRootPart().Root)
    
for comp in GetRootPart().GetAllComponents():
  ComponentHelper.DeleteEmptyComponents(Selection.Create(comp))

myPowSel=PowerSelection.Bodies.ByVolume(myFilter, None, \
 SearchCriteria.SizeComparison.SmallerOrEqual)
myPowSelInv=Selection.Create(GetRootPart().GetAllBodies())-myPowSel
result = ComponentHelper.MoveBodiesToComponent(myPowSel)
result.CreatedComponents[0].SetName("smallBodies")
result = ComponentHelper.MoveBodiesToComponent(myPowSelInv)
result.CreatedComponents[0].SetName("bigBodies")

#Demo 1: Creating cylinders by extruding surfaces
ClearAll()
Diameter = [10, 30, 20, 40, 60]
Length   = [50, 75, 25, 10, 60]
z_offset = 100    
# cylinder creation version 1 
for i in range(len(Diameter)):
  myFace = CircularSurface.Create(Diameter[i]/2,
    Direction.DirZ,
    Point.Create(0, 0,
      sum(Length[:i])-Length[0] + z_offset)).CreatedBody.Faces
  options = ExtrudeFaceOptions()
  options.ExtrudeType = ExtrudeType.ForceIndependent
  result = ExtrudeFaces.Execute(Selection.Create(myFace), Length[i], options)
  result.CreatedBodies[0].SetName("Cylinder_v1_"+str(i))
Selection.Clear()
ViewHelper.ZoomToEntity()

# Solidify Sketch
mode = InteractionMode.Solid
result = ViewHelper.SetViewMode(mode)

# Demo 2
# cylinder creation version 2
for i in range(len(Diameter)):
  CenterBottom=Point.Create(0, (sum(Length[:i]) - Length[0]) + z_offset, 0)
  CenterTop=Point.Create(CenterBottom.X,
                           CenterBottom.Y + Length[i], CenterBottom.Z)
  DragPoint=Point.Create(Diameter[i]/2.,
      CenterTop.Y, CenterTop.Z)
  result=CylinderBody.Create(CenterBottom,
                             CenterTop, DragPoint, ExtrudeType.ForceIndependent)
  result.CreatedBodies[0].SetName("Cylinder_v2_"+str(i))
Selection.Clear()
ViewHelper.ZoomToEntity()

# Solidify Sketch
mode = InteractionMode.Solid
result = ViewHelper.SetViewMode(mode)

#Demo 3
ClearAll()
from math import tan, pi
ConeHeight=0.02
ConeAngle=DEG(30)
 
ViewHelper.SetSketchPlane(Plane.PlaneXY)
 
pt1 = Point2D.Create(0, 0)
pt2 = Point2D.Create(0, ConeHeight)
pt3 = Point2D.Create(ConeHeight*tan(ConeAngle/2), 0)
 
SketchLine.Create(pt1, pt2)
SketchLine.Create(pt2, pt3)
SketchLine.Create(pt3, pt1)
 
result=ViewHelper.SetViewMode(InteractionMode.Solid)
 
mySel=Selection.Create(result.CreatedBodies[0].Faces)
myAxis = Line.Create(Point.Origin,Direction.DirY)
myOptions = RevolveFaceOptions()
myOptions.ExtrudeType = ExtrudeType.Add
RevolveFaces.Execute(mySel, myAxis, DEG(360), myOptions)
 
Selection.Clear()
ViewHelper.ZoomToEntity()

# Demo 4
ClearAll()
pt1=Point.Origin
pt2=Point.Create(MM(10), MM(2), MM(2))
 
result=BlockBody.Create(pt1, pt2, ExtrudeType.Add)
b0=result.CreatedBody
for i in range(10):
    mySel = Selection.Create(b0)
    direction = Direction.DirY
    options = MoveOptions()
    options.Copy = True
    result = Move.Translate(mySel, direction, (i+1)*MM(10), options)
Selection.Clear()
ViewHelper.ZoomToEntity()

# Demo 5
ClearAll()
pt1=Point.Create(MM(-10),MM(0),MM(0))
pt2=Point.Create(pt1.X+MM(2), pt1.Y+MM(2), pt1.Z+MM(2))
 
result=BlockBody.Create(pt1, pt2, ExtrudeType.Add)
b0=result.CreatedBody
for i in range(11):
    mySel = Selection.Create(b0)
    axis = Line.Create(Point.Origin, Direction.DirZ)
    options = MoveOptions()
    options.Copy = True
    result = Move.Rotate(mySel, axis, (i+1)*DEG(30), options)
Selection.Clear()
ViewHelper.ZoomToEntity()

# Demo
from SpaceClaim.Api.V21 import Command
import os
ClearAll()
#Import the geometry
my_path = os.path.dirname(GetActiveWindow().Document.Path)
DocumentInsert.Execute(os.path.join(my_path, "valve1.dsco"))
Selection.Create(GetRootPart().Components[0]).SetActive()
c = Command.GetCommand("ImportComponentGroups")
c.Execute()
ViewHelper.ZoomToEntity()
 
#Fill the surface holes < criteria
criteria_radius = MM(7)
total_selection = Selection.Empty()
selection1 = PowerSelection.Faces.BySurfaceHoleRadius(criteria_radius, 
    PowerSelectOptions(True), 
    SearchCriteria.SizeComparison.SmallerOrEqual)
total_selection += selection1
total_selection.SetActive()
result = Fill.Execute(total_selection)
 
#Remove all chamfers and rounds
criteria_radius = MM(20)
total_selection = PowerSelection.Faces.ByRoundRadius(criteria_radius, 
    PowerSelectOptions(True), 
    SearchCriteria.SizeComparison.SmallerOrEqual, 
    SearchCriteria.RoundType.All)
for body in GetRootPart().GetAllBodies():
    for face in body.Faces:
        if isinstance(face.Shape.Geometry, Cone):
            total_selection += Selection.Create(face)
total_selection.SetActive()
result = Fill.Execute(total_selection)
 
#Create missing bodies from Named Selections and move them to new components 
ComponentHelper.SetActive(Selection.Create(GetRootPart().Components[0]), None) 
options = LoftOptions()
options.IsRuled = True

selection = Selection.CreateByGroups("Right_elbow_in") 
selection += Selection.CreateByGroups("Right_connector_out") 
result = Loft.Create(selection, None, options) 
selection = Selection.Create(result.CreatedBodies[0]) 
result = ComponentHelper.MoveBodiesToComponent(selection) 
result.CreatedComponents[0].SetName("Right_connector") 
 
selection = Selection.CreateByGroups("Left_elbow_in") 
selection += Selection.CreateByGroups("Left_connector_out") 
result = Loft.Create(selection, None, options)
selection = Selection.Create(result.CreatedBodies[0]) 
result = ComponentHelper.MoveBodiesToComponent(selection) 
result.CreatedComponents[0].SetName("Left_connector")
 
#Simplify 1 body
body = GetActivePart().GetAllComponents("Valve")[0].GetBodies()[0]
zmax = 0
for face in body.Faces:
  if face.EvalMid().Point.Z > zmax:
    zmax = face.EvalMid().Point.Z
    my_face = face
selection = Selection.Create(my_face) +  Selection.Create(my_face.AdjacentFaces)
result = Fill.Execute(selection)

# Remove holes of radius 3mm
sel = PowerSelection.Faces.BySurfaceHoleRadius(MM(3),
       PowerSelectOptions(False, BodySelection.Create(GetRootPart().Bodies[0])),
       SearchCriteria.SizeComparison.Equal)
secondarySelection = Selection.Empty()
options = FillOptions()
result = Fill.Execute(sel, secondarySelection, options, FillMode.ThreeD)

# Translate bigger hole Along X Handle
circ_face = PowerSelection.Faces.BySurfaceHoleRadius(MM(35),
       PowerSelectOptions(False, BodySelection.Create(GetRootPart().Bodies[0])),
       SearchCriteria.SizeComparison.Equal)
direction = Direction.Create(1, 0, 0)
options = MoveOptions()
result = Move.Translate(circ_face, direction, MM(45), options)

# Translate (copy) bigger hole Along X Handle
direction = Direction.Create(1, 0, 0)
options = MoveOptions()
options.CreatePatterns = True
options.Copy = True
result = Move.Translate(circ_face, direction, MM(-90), options)

# Create Fluid Volume
part = GetRootPart()
body = part.Bodies[0]
ymin = 0
ymax = 0
zmax = 0
# access faces with openings (ymin, ymax, zmax)
for face in body.Faces:
    if face.EvalMid().Point.Y < ymin:
        ymin = face.EvalMid().Point.Y
        ymin_face = face
    if face.EvalMid().Point.Y > ymax:
        ymax = face.EvalMid().Point.Y
        ymax_face = face
    if face.EvalMid().Point.Z > zmax:
        zmax = face.EvalMid().Point.Z
        zmax_face = face
options = VolumeExtractOptions()
selection = FaceSelection.Create(ymin_face, ymax_face, zmax_face)
#select seed face
secondarySelection = circ_face
result = VolumeExtract.Create(selection, secondarySelection, options)

#----------------------------------EXTERNAL CONNECTIONS-------------------------
#Reference to Microsoft Excel
ClearAll()
clr.AddReference("Microsoft.Office.Interop.Excel")
import Microsoft.Office.Interop.Excel as Excel
import os

mypath = os.path.dirname(GetActiveWindow().Document.Path)
myExcel = Excel.ApplicationClass()
myExcel.Visible = True
excel_file_name = "read_excel.xlsx"
workbook = myExcel.Workbooks.Open(os.path.join(mypath,excel_file_name))
#or myWorkSheet = workbook.Worksheets("Sheet1")
myWorkSheet = workbook.Worksheets[1]  
#Read data from Excel file
i = 1 
myX = ""
wloc = True
points = List[Point2D]()
while wloc:
  myX = myWorkSheet.Rows[i].Value2[0,0]
  if not isinstance(myX, str):
    myY = myWorkSheet.Rows[i].Value2[0,1]
    points.Add(Point2D.Create(MM(myX), MM(myY)))
  i = i+1
  if myX == "End":
    wloc = False
workbook.Close()
myExcel.Quit()
#create spline curve from imported point data and create a surface body
ViewHelper.SetSketchPlane(Plane.PlaneXY)
result = SketchNurbs.CreateFrom2DPoints(True, points)
ViewHelper.SetViewMode(InteractionMode.Solid)
ViewHelper.ZoomToEntity()

Contact us
Disclaimers and Policies

The content on CFDyna.com is being constantly refined and improvised with on-the-job experience, testing, and training. Examples might be simplified to improve insight into the physics and basic understanding. Linked pages, articles, references, and examples are constantly reviewed to reduce errors, but we cannot warrant full correctness of all content.