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

PyFluent example codes

fluent.docs.pyansys.com/ version/ stable/ user_guide/ index.html#ref-user-guide should be the starting point to learn how to use PyFluent. This is a compilation of codes or syntax used in PyFluent. The attempt is to create functions which can be turned on and off based on requirements of the simulation physics. field_data object is an attribute of the Solver object where "field_data = solver.fields .field_data" and solver is a Fluent session started by solver = pyfluent .launch_fluent(mode = pyfluent.FluentMode .SOLVER)
import ansys.fluent.core as pyfluent - the statement to import core functionality. session = pyfluent.launch_fluent(): without any argument, this starts a solver session (i.e. Solution mode) and without GUI. There are two modes of PyFLUENT API: (a) the TUI API which follows syntax similar to FLUENT TUI and (b) Settings API which is equivalent to GUI or Model Tree Approach. In Settings API, the option selected through toggle or check buttons are activated using .enabled = True such as session.setup .models .energy .enabled = True or energy.enabled .set_state(True) or session.setup .models .energy .enabled('yes') where ".enabled = True" is replaced by ('yes'). The items which are selected by user is typically provided as arguments: solver.tui .define .units("length", "mm") where the variable 'length' and unit 'mm' are selected by user in the GUI window. Note the equivalent Scheme command is "define units length mm".
To record TUI commands as PyFLUENT script, type in the TUI: (api-start-python-journal "py_fluent.py"). To stop: (api-stop-python-journal). Like many standard IDE, press tab after dot (.) in the command syntax to get options in drop-down items. For example, session.file.read. and press tab key to get available options. Use keywords arguments and argument_names to get names of arguments required. For example: session.file .read .argument_names. Alternatively, args = session.solver .file .read_case .get_arguments(), print(args).
Like any OOP-language, following two methods can be used based on users' preferences:
  outlet = solver.setup.boundary_conditions.pressure_outlet[b_outlet]
  outlet.turbulence.turb_intensity = 2.5
--or--
  solver.setup.boundary_conditions.pressure_outlet[b_outlet]
    .turbulence.turbulent_intensity = 2.5
As in OOP: the 'object' 'Solver' session provides child 'objects' for solver settings and field data access respectively. Get these fields and settings children by calling dir(solver). To get children of fields and settings, use dir(solver.fields) and dir(solver.settings) respectively. To find out more about each item in PyFluent, use Python help() function: help(solver.settings.file.read_case). The CaseFile class allows you to access Fluent case information without a live Fluent session. The FileSession class mimics the functionality of live session objects, allowing you to access field data and other relevant information without a live Fluent session.
from pathlib import Path
from pprint import pprint

import ansys.fluent.core as pyfluent
from ansys.fluent.core import examples
from ansys.fluent.core.filereader.case_file import CaseFile
from ansys.fluent.core.filereader.case_file import DataFile

from ansys.fluent.visualization import set_config
import ansys.fluent.visualization.pyvista as pv
from ansys.units import Quantity
Here ansys.fluent.core is the main Python package. Inside it, there are many modules such as filereader, meshing, solver, session_meshing, session_solver... Each Module shall contain multiple classes and associated Methods. In the example offline_reader = CaseFile(case_file_name = "Case1.cas.gz"), offline_reader is an object of class CaseFile.

One may also infer class and variables by the naming convention: PyFLUENT uses Pascal case to name Classes and snake case to name objects, variables and methods. One can create own sign convention such as Pascal-snake case combination (e.g. Geom_File_Name) but a convention is needed to make consistent and reusable scripts.

session.setup.models.viscous() - prints all options for turbulence model currently defined. Note models is an object in FLUENT model-tree.
session.setup .materials() - prints currently defined materials and their properties. session.setup .cell_zone_conditions .fluid()- prints all defined cell-zones and their properties
session.setup.cell_zone_conditions.fluid['zone_x'](material='water-liquid') - Note that the object "Cell Zone Conditions" in model tree is accessed by cell_zone_conditions. The domain names are specified as list inside [...] and arguments are specified inside (...).
Longer sentences can be broken into smaller and the name of variables can also be same as built-in variable inside PyFluent. There are different views on dot operator: "It is just a syntactic element that denotes the seperation of variable name holding an object and the object's property or seperates package names and classes." An alternate view is: ". is certainly an operator, a binary operator. The left operand resolves to some module in the program and the right one resolves to a sub-module of the left hand. It has left-to-right associativity." Refer: stackoverflow.com/ ... /what-is-the-purpose-of-java-dot-operator.
session = pyfluent.launch_fluent()
fields = session.fields
field_data = fields.field_data
transaction = field_data.new_transaction()
pressure_fields = transaction.get_fields()
When a fluent session is already opened with Python console, session = pyfluent.launch_fluent() is not required though import ansys.fluent.core as pyfluent is required. The class and function can be directly access such as meshing.File.ReadMesh(FileName = file_name). With Python console, the options generated with Enter key press in classical Scheme console is not available.
  • meshing.tui.display: prints options available for display method / class. Options with further sub-classes are printed with suffix '.'
  • meshing.tui.display.boundary_cells() and meshing.tui.display.redisplay - draw all boundaries.
  • meshing.tui.mesh: displays options such as auto_mesh, check_mesh, manage., modify. and many others.
  • Replace meshing. with solver. when FLUENT is opened in solver mode.
  • In console, type dir() to get top (root) level classes.
  • Type dir(solver) to get classes and methods under 'solver' class.
  • Type help(solver.setup) to get further information about an object or class or method.
setup class in PyFluent has sub-classes aligned to the model tree: 'general' accessed as setup.general and others are [models, materials, cell_zone_conditions, boundary_conditions, mesh_interface...]. The 'models' object expands to [multiphase, energy, viscous, radiation...] which can be accessed by setup.models.multiphase...
# ------------------------OFFLINE FEATURES-------------------------------------
offline_reader = CaseFile(case_file_name = "Case1.cas.gz")
# Check precision and dimension of set-up
offline_reader.precision()
offline_reader.num_dimensions()

# Get input and output paramters defined in the case as 'dictionaries'
{par.name: par.value for par in offline_reader.input_parameters()}
{par.name: par.units for par in offline_reader.output_parameters()}

offline_reader.get_mesh().get_surface_names()

offline_reader_data = DataFile(data_file_name="Case1-2500.dat.gz", 
  case_file_handle=CaseFile("Case1.cas.gz"))
Example code: Generate summary of a simulation set-up:
def generate_summary():
  session = pyfluent.launch_fluent()
  session.setup()
  
  # Extracting simulation details
  case_file = session.solution.name
  mesh_file = session.mesh.name
  # Getting physics and solver settings
  solver_type = session.setup.type
  time_stepping = session.setup.time_stepping
  # Getting boundary conditions
  boundary_conditions = session.setup.boundary_conditions
  # Getting material properties
  materials = session.materials.list()
  # Getting discretization schemes 
  discretization_schemes = session.setup.discretization 
  # Getting defined monitors 
  monitors = session.solution.monitors.list() 
  # Getting residual limits for convergence 
  residuals = session.solution.residual
  
  # Print summary
  print("-----Simulation Summary-----") 
  
  print(f"Case File: {case_file}")
  print(f"Mesh File: {mesh_file}")
  print(f"Solver Type: {solver_type}")
  print(f"Time Stepping: {time_stepping}")
  
  print("\nBoundary Conditions:")
  for bc in boundary_conditions:
    print(f" - {bc.name}: {bc.type}")
  print("\nMaterials:")
  for material in materials:
    print(f" - {material.name}: {material.type}")
  
  print("\nDiscretization Schemes:")
  for scheme in discretization_schemes:
    print(f" - {scheme.type}: {scheme.scheme}")
  
  print("\nDefined Monitors:")
  for monitor in monitors:
    print(f" - {monitor.name}: {monitor.type}")
  
  print("\nResidual Limits for Convergence:")
  for residual in residuals:
    print(f" - {residual.name}: {residual.limit}")
# Call the function to generate the summary
generate_summary()
#------------------------------------------------------------------------------
#------------------------------------USER INPUTS: MESH-------------------------
geom_filename   = "D:\Projects\Geom.stp"
save_path       = Path("D:\Projects")
mesh_file       = "D:\Projects\Case1-Srf.msh.gz"
save_mesh       = "D:\Projects\Case1-Vol.msh.gz"
# Configure specific settings
set_config(blocking=True, set_view_on_display="isometric")

# Surface Mesh settings
Curv_Norm_Angle = 8
Growth_Rate     = 1.1
Max_Size        = 8
Min_Size        = 1
SizeFunc        = "Curvature"

# Boundary layer settings
BLControlName   = "smooth-transition_1"
BL_Num_Layers   = 10
BL_GrowthRate   = 1.15
BL_Trans_Ratio  = 0.5

# BOI settings
BOI_GrowthRate  = 1.10
BOI_Size        = 2.0

# Volume fill settings
vol_mesh_type   = "poly-hexcore"

# ------------------------------SOLVER INPUTS [SI UNITs]-----------------------
case_file       = "D:\Projects\Case-1.cas.gz"
mesh_file       = "D:\Projects\Case-1.msh.gz"
journ_file      = "D:\Projects\setup.jou"
physics_type    = "steasy_state"  # "transient"
viscous_model   = "k-epsilon"     # "k-omega"
wall_func_model = "realizable"    # "standard", "scalable"

rho_w           = 1000
rho_a           = 1.178
mu_w            = 0.001
mu_a            = 1.2e-6

# Zone and boundary names
c_fluid         = "zn_f_air"
c_solid         = "zn_s_heatsink"
c_porous        = "zn_p_cac"

b_inlet         = "inlet"
b_inlet_v       = 5.0
b_inlet_p       = 500
b_inlet_mf      = 0.25
b_inlet_t       = 313.15

# "Intensity and Viscosity Ratio"
b_inlet_turb    = "Intensity and Hydraulic Diameter" 
b_inlet_ti      = 0.05
b_inlet_tvr     = 5.0
b_inlet_area    = 0.10
b_inlet_dh      = 0.025          # Hydraulic diameter at inlet

b_outlet        = "outlet"
b_outlet_t      = 313.15
b_outlet_p      = 100

w_htc           = 20.0
w_htc_ref_t     = 298
w_em_default    = 0.80
w_em_polished   = 0.10

op_pressure     = 101325
ref_den         = 1.178
init_vx         = 0.01
init_vy         = 0.01
init_vz         = 0.05
init_t          = 313.1
init_type       = "standard" #"hybrid"

# Relaxation factors
urf_mom     = 0.5
urf_pr     = 0.5
urf_ke     = 0.5
urf_tv     = 0.5
urf_tp     = 0.5

m_residual      = 1.0e-4
v_residual      = 1.0e-5
t_residual      = 1.0e-7
ke_residual     = 1.0e-4
n_iter          = 4000
t_step          = 1.0e-3
duration        = 10.0
iter_per_step   = 20
count_t_steps   = duration / t_step

# Post-process parameters
t_min           = 300
t_max           = 400
v_max           = 10
p_max           = 1000
p_min           = -250
#------------------------------------------------------------------------------
# These statements are valid for BATCH mode session. For GUI mode, replace
# session_solve. with meshing. or solver. for respective modes.
#------------------------------------------------------------------------------
# Launch Fluent session with meshing mode
session_mesh = pyfluent.launch_fluent(mode="meshing", ui_mode="gui",
  product_version=pyfluent.FluentVersion.v241,
  precision=pyfluent.Precision.DOUBLE, cleanup_on_exit=True, 
  )

session_mesh.health_check.status()
session_mesh.meshing.File.ReadMesh(FileName=mesh_file)

#session_mesh.meshing.File.WriteMesh(FileName=save_mesh)
session_mesh.journal.start(file_name="pyfluent-journal.py")

workflow = session_mesh.workflow
workflow.InitializeWorkflow(WorkflowType="Watertight Geometry")
workflow.TaskObject["Import Geometry"].Arguments = dict(FileName=geometry_filename)
workflow.TaskObject["Import Geometry"].Execute()

# Add Local Face Sizing
add_local_sizing = workflow.TaskObject["Add Local Sizing"]
add_local_sizing.Arguments = dict(
  {
    "AddChild": "yes",
    "BOIControlName": "facesize_front",
    "BOIFaceLabelList": ["wall_wake"],
    "BOIGrowthRate": BOI_GrowthRate,
    "BOISize": BOI_Size,
  }
)
add_local_sizing.Execute()

# Add BOI (Body of Influence) Sizing
add_boi_sizing = workflow.TaskObject["Add Local Sizing"]
add_boi_sizing.InsertCompoundChildTask()
add_boi_sizing.Arguments = dict(
  {
    "AddChild": "yes",
    "BOIControlName": "boi_wake",
    "BOIExecution": "Body Of Influence",
    "BOIFaceLabelList": ["bluff-body-boi"],
    "BOISize": BOI_Size,
  }
)
add_boi_sizing.Execute()
add_boi_sizing.InsertCompoundChildTask()

# Add Surface Mesh Sizing
generate_surface_mesh = workflow.TaskObject["Generate the Surface Mesh"]
generate_surface_mesh.Arguments = dict(
  {
    "CFDSurfaceMeshControls": {
      "CurvNormalAngle": Curv_Norm_Angle,
      "GrowthRate": Growth_Rate,
      "MaxSize": Max_Size, "MinSize": Min_Size,
      "SizeFunctions": "Curvature",
    }
  }
)
generate_surface_mesh.Execute()
generate_surface_mesh.InsertNextTask(CommandName="ImproveSurfaceMesh")
improve_surface_mesh = workflow.TaskObject["Improve Surface Mesh"]
improve_surface_mesh.Arguments.update_dict({"FaceQualityLimit": 0.4})
improve_surface_mesh.Execute()

# Describe Geometry, Update Boundaries, Update Regions
workflow.TaskObject["Describe Geometry"].Arguments = dict(
  CappingRequired="Yes",
  SetupType="The geometry consists of only fluid regions with no voids",
)
workflow.TaskObject["Describe Geometry"].Execute()
workflow.TaskObject["Update Boundaries"].Execute()
workflow.TaskObject["Update Regions"].Execute()

# Add Boundary Layers
add_boundary_layers = workflow.TaskObject["Add Boundary Layers"]
add_boundary_layers.AddChildToTask()
add_boundary_layers.InsertCompoundChildTask()
workflow.TaskObject["smooth-transition_1"].Arguments.update_dict(
  {
    "BLControlName": "smooth-transition_1",
    "NumberOfLayers": BL_Num_Layers,
    "Rate": BL_GrowthRate,
    "TransitionRatio": BL_Trans_Ratio,
  }
)
add_boundary_layers.Execute()

# Generate the Volume Mesh
generate_volume_mesh = workflow.TaskObject["Generate the Volume Mesh"]
generate_volume_mesh.Arguments.update_dict({"VolumeFill": vol_mesh_type})
generate_volume_mesh.Execute()
#------------------------------------------------------------------------------
# ---------------Solver Setup and Solve Workflow-------------------------------
# These statements are valid for BATCH mode session. For GUI mode, replace
# session_solve. with meshing. or solver. for respective modes.
#------------------------------------------------------------------------------
# Switch to the Solver Mode or Launch solver directly
session_mesh.switch_to_solver()
setup, solution = solver.settings.setup, solver.settings.solution
session_solve = pyfluent.launch_fluent(product_version=pyfluent.FluentVersion.v241,
  precision=pyfluent.Precision.DOUBLE, processor_count=2, 
  dimension=pyfluent.Dimension.THREE, ui_mode="gui",
  mode="solver", case_data_file_name = case_name or case_file_name = case_name,
  journal_file_names=journ_name
)
session_solve.file.read_mesh(file_name=mesh_file)
session_solve.file.read(file_type="mesh", file_name=mesh_file)

session_solve.file.read_case(file_type="case", file_name=case_file)
session_solve.tui.file.read_case(case_file)
session_solve.file.write_case(file_name=case_file)

session_solve.mesh.check()
# ---------------Define Materials and Boundary Conditions----------------------
# -----------------------------------------------------------------------------
session_solve.settings.setup.models.viscous.model = viscous_model
session_solve.settings.setup.models.viscous.k_epsilon_model = wall_func_model

viscous = session_solve.setup.models.viscous
viscous.model = "k-omega"
viscous.k_omega_model = "sst"

session_solve.settings.setup.models.viscous.options.curvature_correction = True
session_solve.setup.models.energy.enabled = True
#session_solve.settings.setup.models.energy = {"enabled": True}
session_solve.setup.models.multiphase.models = "mixture"
session_solve.tui.define.models.multiphase.mixture_parameters("no", "implicit")

session_solve.tui.define.materials.change_create("air", "air", "yes", "constant", ref_den)
air = session_solve.setup.materials.fluid["air"]
air.density.option = "ideal-gas"
air.viscosity.option = "sutherland"
air.viscosity.sutherland.option = "three-coefficient-method"
air.viscosity.sutherland.reference_viscosity = 1.716e-05
air.viscosity.sutherland.reference_temperature = 273.11
air.viscosity.sutherland.effective_temperature = 110.56

#session_solve.setup.materials.copy_database_material_by_name(type="fluid", name="water")
session_solve.setup.materials.database.copy_by_name(type="fluid", name="water-liquid")
session_solve.setup.materials.database.copy_by_name(type="fluid", name="water-vapor")
session_solve.setup.materials.fluid["water-vapor"] = {
  "density": {"value": 0.02558},
  "viscosity": {"value": 1.26e-06},
}

session_solve.tui.define.phases.set_domain_properties.change_phases_names("vapor", "liquid")
session_solve.tui.define.phases.set_domain_properties
  .phase_domains.liquid.material("yes", "water-liquid")
session_solve.tui.define.phases.set_domain_properties
  .phase_domains.vapor.material("yes", "water-vapor")

session_solve.tui.define.materials.copy("solid", "steel")
session_solve.settings.setup.cell_zone_conditions.solid["heat_sink"].material = "aluminum"
glass = session_solve.settings.setup.materials.solid.create("glass")
glass.set_state(
  {
    "chemical_formula": "",
      "density": {
        "option": "constant",
        "value": 2650,
      },
      "specific_heat": {
        "option": "constant",
        "value": 1887,
      },
      "thermal_conductivity": {
        "option": "constant",
        "value": 7.6,
      },
      "absorption_coefficient": {
        "option": "constant",
        "value": 5.302,
      },
      "refractive_index": {
        "option": "constant",
        "value": 1.4714,
      },
  }
)
plastic = session_solve.settings.setup.materials.solid.create("plastic")
plastic.chemical_formula = ""
plastic.density.value = 1250
plastic.specific_heat.value = 750
plastic.thermal_conductivity.value = 0.20
plastic.absorption_coefficient.value = 0
plastic.refractive_index.value = 1
#
session_solve.setup.cell_zone_conditions.fluid["z_fluid"].general.material = "water-liquid"
session_solve.setup.materials.fluid["water-liquid"] = {
  "density": {
    "option": "constant", "value": rho_w,
  },
  "viscosity": {
     "option": "constant","value": mu_w,
  },
}
# Get list of wall and cell zones
zn_state = session_solve.settings.setup.cell_zone_conditions.get_state()
bc_state = session_solve.settings.setup.boundary_conditions.get_state()
w_zones = list(bc_state["wall"].keys())

# Define Boundary Conditions
inlet = session_solve.settings.setup.boundary_conditions.velocity_inlet[b_inlet]
inlet.turbulence.turbulence_specification = "Intensity and Hydraulic Diameter"
inlet.turbulence.turbulent_intensity = b_inlet_ti
inlet.momentum.velocity.value = b_inlet_v
inlet.turbulence.turbulent_viscosity_ratio = b_inlet_tvr
inlet.turbulence.hydraulic_diameter = "50 [mm]"
hyd_d = solver.settings.setup.boundary_conditions.velocity_inlet[b_inlet]
  .turbulence.hydraulic_diameter
hyd_d.set_state(Quantity(b_inlet_dh, "m"))
inlet.thermal.temperature.value = b_inlet_t

outlet = session_solve.settings.setup.boundary_conditions.pressure_outlet[b_outlet]
outlet.turbulence.turb_intensity = b_inlet_tvr/2.0

session_solve.setup.boundary_conditions.pressure_outlet[b_outlet]
  .turbulence.turbulent_viscosity_ratio = 4

# Define HTC
session_solve.tui.define.boundary_conditions.set.wall(
  "wall-outer", "wall-enclosure", "()",
  "thermal-bc", "yes", "convection",
  "convective-heat-transfer-coefficient",
  "no", w_htc, "q",
)
# Copy settings from one zone to other
session_solve.settings.setup.cell_zone_conditions.copy(
  from = "bracket",
  to = ["tank_up", "tank_dn", "shell_o", "shell_i"])
# Define radiation settings
w_heatsink = session_solve.settings.setup.boundary_conditions.wall["w-heat-sink"]
w_heatsink.thermal.material = "aluminum"
w_heatsink.radiation.radiation_bc = "Opaque"
w_heatsink.radiation.internal_emissivity = w_em_default
w_heatsink.radiation.diffuse_fraction_band = {"s-": 1}

# Define Reference Values
session_solve.settings.setup.reference_values.area = inlet_area
session_solve.settings.setup.reference_values.density = ref_density
session_solve.settings.setup.reference_values.velocity = inlet_velocity
solver.setup.general.operating_conditions.operating_pressure = op_pressure
User Defined Functions
udf_lib_name = 'libudf'
session.tui.define.user_defined.use_built_in_compiler('yes')
session.tui.define.user_defined.compiled_functions('compile', udf_lib_name, 'yes',
  "udf_func.c"', ',')
session.tui.define.user_defined.compiled_functions ('load', udf_lib_name)
Load a precompiled UDF using: scheme_eval(f' (open-udf-library "{libname}" {udf_name})')
# -----------------Define Report Definitions-----------------------------------
# These statements are valid for BATCH mode session. For GUI mode, replace
# session_solve. with meshing. or solver. for respective modes.
#------------------------------------------------------------------------------
session_solve.settings.solution.report_definitions.drag["cd-mon1"] = {}
session_solve.settings.solution.report_definitions.drag["cd-mon1"] = {
  "zones": ["wall_x", "wall_y", "wall_z"], "force_vector": [0, 0, 1],
}
session_solve.parameters.output_parameters.report_definitions.create(name="parameter-1")
session_solve.parameters.output_parameters.report_definitions["parameter-1"] = {
  "report_definition": "cd-mon1"
}
session_solve.settings.solution.monitor.report_plots.create(name="cd-mon1")
session_solve.settings.solution.monitor.report_plots["cd-mon1"] = {"report_defs": ["cd-mon1"]}

session_solve.settings.solution.report_definitions.volume["max-t-solids"] = {}
session_solve.settings.solution.report_definitions.volume["max-t-solids"].report_type = "volume-max"
session_solve.settings.solution.report_definitions.volume["max-t-solids"] = {
  "field": "temperature", "cell_zones": ["hs-1", "hs-2"],
}
session_solve.settings.solution.report_definitions.volume["max-t-fluid"] = {}
session_solve.settings.solution.report_definitions.volume["max-t-fluid"].report_type = "volume-max"
session_solve.settings.solution.report_definitions.volume["max-t-fluid"] = {
  "field": "temperature", "cell_zones": ["fluid", "porous"],
}
report_file_path = "max-temperature.out"
session_solve.settings.solution.monitor.report_files.create(name="max-temperature")
session_solve.settings.solution.monitor.report_files["max-temperature"] = {
  "report_defs": ["max-t-solids", "max-t-fluid"],
  "file_name": str(report_file_path),
}
session_solve.settings.solution.monitor.report_files["max-temperature"].report_defs = [
  "max-t-solids",
  "max-t-fluid",
  "flow-time",
]
# -----------------------------------------------------------------------------
# -----------------Define, Initialize and Run Solver---------------------------
# -----------------------------------------------------------------------------
# Define Solver Settings
session_solve.tui.solve.set.p_v_coupling(24)
#solver.solution.methods.p_v_coupling.flow_scheme = "Coupled"
session_solve.tui.solve.set.discretization_scheme("pressure", 12)
session_solve.tui.solve.set.discretization_scheme("k", 1)
session_solve.tui.solve.set.discretization_scheme("epsilon", 0.1)
session_solve.tui.solve.initialize.set_defaults("k", 0.001)

methods = solver.solution.methods
methods.discretization_scheme = {
  "k": "first-order-upwind",
  "mom": "quick",
  "mp": "quick",
  "omega": "first-order-upwind",
  "pressure": "presto!",
}

session._solve.settings.solution.monitor.residual.equations["continuity"]
 .absolute_criteria = m_residual
'''
resid_eqns = solver.solution.monitor.residual.equations
resid_eqns["continuity"].absolute_criteria = m_residual
session_solve.solution.monitor.residual.options.criterion_type = "none"
session_solve.solution.monitor.residual.options.criterion_type = "absolute"
 '''
session_solve.settings.solution.monitor.residual.equations["x-velocity"]
 .absolute_criteria = v_residual
session_solve.settings.solution.monitor.residual.equations["y-velocity"]
 .absolute_criteria = v_residual
session_solve.settings.solution.monitor.residual.equations["z-velocity"]
 .absolute_criteria = v_residual
session_solve.settings.solution.monitor.residual.equations["k"]
 .absolute_criteria = ke_residual
session_solve.settings.solution.monitor.residual.equations["epsilon"]
 .absolute_criteria = ke_residual
# Disable plotting of residuals during the calculation.
# solver_solve.solution.monitor.residual.options.plot = False
# Steady State Run
session_solve.settings.solution.run_calculation.iter_count = n_iter
session_solve.settings.solution.initialization.initialization_type = init_type
#solver.solution.initialization.hybrid_initialize()
session_solve.settings.solution.initialization.standard_initialize()
session_solve.tui.solve.set.equations("flow", "no", "kw", "no")
session_solve.settings.solution.run_calculation.iterate(iter_countn=n_iter)

# Transient run
#session_solve.tui.define.models.unsteady_2nd_order("yes")
#session_solve.tui.solve.dual_time_iterate(count_t_steps, iter_per_step)
session_solve.settings.setup.general.solver.time = "unsteady-2nd-order-bounded"
session_solve.settings.solution.run_calculation.transient_controls.time_step_size = t_step
session_solve.settings.solution.run_calculation.dual_time_iterate(
    time_step_count=count_t_steps, max_iter_per_step=iter_per_step
)
# -----------------Post-Processing Workflow------------------------------------
# These statements are valid for BATCH mode session. For GUI mode, replace
# session_solve. with meshing. or solver. for respective modes.
# -----------------------------------------------------------------------------
# Check mass balance
session_solve.solution.report_definitions.flux["mass_flow_rate"] = {}
mass_flow_rate = session_solve.solution.report_definitions.flux["mass_flow_rate"]
mass_flow_rate.boundaries.allowed_values()
mass_flow_rate.boundaries = [b_inlet, b_outlet]
mass_flow_rate.print_state()
session_solve.solution.report_definitions.compute(report_defs=["mass_flow_rate"])

session_solve.fields.reduction.area_average(
  expression="AbsolutePressure",
  locations=solver.settings.setup.boundary_conditions.velocity_inlet
)
session_solve.fields.reduction.area(
  locations=[solver.settings.setup.boundary_conditions.velocity_inlet[b_inlet]]
)
# or use the context argument
session_solve.fields.reduction.area(locations=["inlet1"], ctxt=session_solve)

graphics = session_solve.results.graphics
if graphics.picture.use_window_resolution.is_active():
    graphics.picture.use_window_resolution = False
graphics.picture.x_resolution = 1920
graphics.picture.y_resolution = 1440

session_solve.tui_preferences.graphics.colormap_settings.number_format_type(var)
where 'var' can be ("general" "float" "exponential")

session_solve.results.surfaces.iso_surface.create(name="plane-yz")
session_solve.results.surfaces.iso_surface["plane-yz"].field = "x-coordinate"
session_solve.results.surfaces.iso_surface["plane-yz"] = {"iso_values": [0]}

graphics_session_pv = pv.Graphics(session_solve)
contour1 = graphics_session_pv.Contours["contour-1"]
contour1.field = "velocity-magnitude"
contour1.surfaces_list = ["plane-yz"]
contour1.display("window-1")

contour2 = graphics_session_pv.Contours["contour-2"]
contour2.field.allowed_values
contour2.field = "temperature"
contour2.surfaces_list = ["plane-yz"]
contour2.display("window-2")

graphics.contour["contour_pr"] = {
  "coloring": {
    "option": "banded", "smooth": False,
  }, "field": "pressure", "filled": True,
}
Quantitative Results:
solver_session.solution.report_definitions.moment['bld_moment']={}
solver_session.solution.report_definitions.moment['bld_moment'].thread_names = w_blades
solver_session.solution.report_definitions.moment['bld_moment'].mom_axis[1, 0, 0]
solver_session.solution.report_definitions.moment['bld_moment'].mon_center(xc, yc, zc]
solver_session.solution.report_definitions.compute(report_defs=["b1d_moment"])
# Create and display velocity vectors and export the image as PNG format
graphics = session_solve.results.graphics
graphics.vector["vv_plane_xy"] = {}
velocity_symmetry = solver.results.graphics.vector["vv_plane_xy"]
velocity_symmetry.print_state()
velocity_symmetry.field = "velocity-magnitude"
velocity_symmetry.surfaces_list = ["plane-xy"]
velocity_symmetry.scale.scale_f = 0.1
velocity_symmetry.style = "arrow"
velocity_symmetry.display()
graphics.views.restore_view(view_name="front")
graphics.views.auto_scale()
graphics.picture.save_picture(file_name="vv_plane_xy.png")

session_solve.settings.results.graphics.contour["temperature"] = {}
session_solve.settings.results.graphics.contour["temperature"] = {
  "field": "temperature",
  "surfaces_list": "wall*",
  "color_map": {
    "visible": True, "size": 10,
    "color": "field-velocity",
    "log_scale": False, "format": "%0.1f",
    "user_skip": 9, "show_all": True, "position": 1,
    "font_name": "Helvetica", "font_automatic": True,
    "font_size": 0.032, "length": 0.54, "width": 6,
    "bground_transparent": True,
    "bground_color": "#CCD3E2",
    "title_elements": "Variable and Object Name",
  },
  "range_option": {
    "option": "auto-range-off",
    "auto_range_off": {"maximum": t_max, "minimum": t_min, "clip_to_range": False},
  },
}
session_solve.settings.results.graphics.views.restore_view(view_name="top")
session_solve.settings.results.graphics.views.camera.zoom(factor=2)
session_solve.settings.results.graphics.views.save_view(view_name="animation-view")
session_solve.settings.solution.calculation_activity
  .solution_animations["animate-temperature"] = {}
session_solve.settings.solution.calculation_activity
  .solution_animations["animate-temperature"] = {
    "animate_on": "temperature",
    "frequency_of": "flow-time",
    "flow_time_frequency": 0.05,
    "view": "animation-view",
}
# -----------------------------------------------------------------------------
# Post processing with PyVista (3D visualization)
# -----------------------------------------------------------------------------
graphics_session_vista = pv.Graphics(session_solve)
contour_t = graphics_session1.Contours["temperature"]
contour_t()  # Check available options and set contour properties
contour_t.field = "temperature"
contour_t.surfaces_list = ["wall-1", "wall-2", "wall-x", "wall_y" ]
contour_t.range.option = "auto-range-off"
contour_t.range.auto_range_off.minimum = t_min
contour_t.range.auto_range_off.maximum = t_max
contour_t.display()

# --------- Save and Exit------------------------------------------------------
save_case_data_as = Path(save_path) / "Project_1.cas.h5"
session_solve.file.write(file_type="case-data", file_name=str(save_case_data_as))
'''
session_solve.file.batch_options.confirm_overwrite = True
session_solve.file.write(file_name="Project_1.cas.h5", file_type="case-data")
'''
session_mesh.journal.stop()
session_solve.exit()
Function to rename zones based on their type and strip characters after colon
 
def rename_zones():
  session = pyfluent.launch_fluent()
  session.setup()
  
  # Get all zones zones = session.setup.zones.list()
  for zone in zones:
    original_name = zone.name
    zone_type = zone.type
    # Strip characters after colon
    if ':' in original_name:
      new_name = original_name.split(':')[0]
    else:
      new_name = original_name
    # Combine zone type and new name: zone type as suffix
    new_name = f"{zone_type}_{new_name}"
    '''
    Alternatively, rename zones with only first letter of zone-type
    # Get the first letter of the zone type 
    prefix = zone_type[0].upper() + '_'
    # Strip characters after colon 
    if ':' in original_name: 
      new_name = prefix + original_name.split(':')[0] 
    else: 
      new_name = prefix + original_name
    '''
    session.setup.zones.rename(zone, new_name)
    print(f"Renamed {original_name} to {new_name}")
Create images of plots for all pairs of case and data files.
def generate_images_from_results(result_files_dir, output_dir): 
  # Ensure output directory exists 
  if not os.path.exists(output_dir): 
    os.makedirs(output_dir) 
  # Loop through each result file in the directory 
  for result_file in os.listdir(result_files_dir): 
    if result_file.endswith('.cas.gz'):
      session session = pyfluent.launch_fluent() 
      session.setup() 
      # Load the result file 
      session.file.read_case(os.path.join(result_files_dir, result_file))
      session.file.read_data(os.path.join(result_files_dir, 
        result_file.replace('.cas.gz', '.dat.gz'))) 

      # Extract defined contour plots and scenes 
      plots = session.setup.plots.list() 
      scenes = session.setup.scenes.list() 
      # Generate and save images for each plot 
      plot_output_dir = os.path.join(output_dir, "plots") 
      if not os.path.exists(plot_output_dir): 
        os.makedirs(plot_output_dir) 
        for plot in plots: 
          image_path = os.path.join(plot_output_dir, f"{result_file}_{plot.name}.png") 
        plot.export_image(image_path) 
        print(f"Saved plot image: {image_path}") 
    
      # Generate and save images for each scene
      for each scene scene_output_dir = os.path.join(output_dir, "scenes") 
        if not os.path.exists(scene_output_dir): 
          os.makedirs(scene_output_dir) 
        for scene in scenes: image_path = os.path.join(scene_output_dir, 
          f"{result_file}_{scene.name}.png")
          scene.export_image(image_path) 
        print(f"Saved scene image: {image_path}") 
          
    session.exit() 
    # Example usage: 
    result_files_dir = "D:/Projects/CHT" 
    output_dir = "D:/Projects/CHT/images"
    generate_images_from_results(result_files_dir, output_dir)
Create images of plots for all transient runs: one case and multiple data files. Note that the case file needs to be read only once:
session session = pyfluent.launch_fluent() 
session.setup()
session.file.read_case(os.path.join(result_files_dir, case_file))
def generate_images_from_results(case_file, result_files_dir, output_dir): 
  # Ensure output directory exists 
  if not os.path.exists(output_dir): 
    os.makedirs(output_dir)
  
  # Loop through each result file in the directory 
  for result_file in os.listdir(result_files_dir):
    session.file.read_data(os.path.join(result_files_dir, result_file) 
    
    # Extract defined contour plots and scenes 
    plots = session.setup.plots.list() 
    scenes = session.setup.scenes.list() 
    # Generate and save images for each plot 
    plot_output_dir = os.path.join(output_dir, "plots") 
    if not os.path.exists(plot_output_dir): 
      os.makedirs(plot_output_dir) 
    for plot in plots: 
      image_path = os.path.join(plot_output_dir, f"{result_file}_{plot.name}.png") 
      plot.export_image(image_path) 
      print(f"Saved plot image: {image_path}") 
     
    # Generate and save images for each scene
    for each scene scene_output_dir = os.path.join(output_dir, "scenes") 
      if not os.path.exists(scene_output_dir): 
        os.makedirs(scene_output_dir) 
      for scene in scenes: image_path = os.path.join(scene_output_dir, 
        f"{result_file}_{scene.name}.png")
        scene.export_image(image_path) 
        print(f"Saved scene image: {image_path}") 
        
    session.exit() 
    # Example usage:
    case_file = "D:/Projects/CHT/CHT.cas.gz"
    result_files_dir = "D:/Projects/CHT" 
    output_dir = "D:/Projects/CHT/images"
    generate_images_from_results(case_file, result_files_dir, output_dir)
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.