Logo of CFDyna.com

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" abd solver is a Fluent session started by solver =
pyfluent.launch_fluent(mode=pyfluent.FluentMode.SOLVER)

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,
call 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 with-
out 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

# ------------------------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"))

#------------------------------------------------------------------------------
#------------------------------------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
CurvNormalAngle = 8
GrowthRate      = 1.1
MaxSize         = 8
MinSize         = 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"

b_inlet         = "inlet"
b_inlet_v       = 5.0
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
hyd_d = solver.settings.setup.boundary_conditions.velocity_inlet[b_inlet]
  .turbulence.hydraulic_diameter
hyd_d.set_state(Quantity(25, "mm"))

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.8
w_em_polished   = 0.08

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

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

#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# 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": 20,
  }
)
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": 8,
      "GrowthRate": 1.15,
      "MaxSize": 8,
      "MinSize": 1,
      "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-------------------------------
#------------------------------------------------------------------------------
# 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": 1000,
  },
  "viscosity": {
     "option": "constant","value": 0.001,
  },
}
# Get list of wall zones
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.turb_intensity = b_inlet_ti
inlet.momentum.velocity.value = b_inlet_v
inlet.turbulence.turb_viscosity_ratio = b_inlet_tvr
inlet.turbulence.hydraulic_diameter = "50 [mm]"
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 = 99000

# -----------------Define Report Definitions-----------------------------------
#------------------------------------------------------------------------------
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 = (0.000001)
'''
resid_eqns = solver.solution.monitor.residual.equations
resid_eqns["continuity"].absolute_criteria = 1e-5
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 = (0.000001)
session_solve.settings.solution.monitor.residual.equations["y-velocity"]
 .absolute_criteria = (0.000001)
session_solve.settings.solution.monitor.residual.equations["z-velocity"]
 .absolute_criteria = (0.000001)
session_solve.settings.solution.monitor.residual.equations["k"]
 .absolute_criteria = (0.000001)
session_solve.settings.solution.monitor.residual.equations["epsilon"]
 .absolute_criteria = (0.000001)
# 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------------------------------------
# -----------------------------------------------------------------------------
# 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.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,
}
# 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": 100,
    "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()
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()