3D field ROM example for images generation#

This example shows how PyTwin can be used to load and evaluate a Twin model in order to visualize ROM results in the form of images with predefined views. The script takes user inputs to evaluate the ROM and will display the corresponding image. A first image is generated using the point cloud based ROM Viewer embedded in the Ansys Digital Twin Runtime, and a second image is generated by loading the ROM results and performing the post processing on the CFD mesh by using PyFluent. Finally, the ROM results are post processing in a 3D Viewer enabled by PyFluent

NOTE :

To generate snapshot files at initialization time, the ROM component included in the Twin must have its parameter “field_data_storage_period” set to 0 and “store_snapshots” set to 1.

To generate images files at initialization time, the ROM component included in the Twin must have the “Embed Geometry” and “Generate Image” options enabled at export time, and its parameter “viewX_storage_period” set to 0.

These parameters can be defined in the Twin Builder subsheet before Twin compilation, or exposed as Twin parameters.

../../_images/TBROM_images_generation.png
# sphinx_gallery_thumbnail_path = '_static/TBROM_images_generation.png'

Import all necessary modules#

import os
import struct

import ansys.fluent.core as pyfluent
from ansys.fluent.visualization import set_config
from ansys.fluent.visualization.pyvista import Graphics
import matplotlib.image as img
import matplotlib.pyplot as plt
from pytwin import TwinModel, download_file

twin_file = download_file("ThermalTBROM_23R1_other.twin", "twin_files")
cfd_file = download_file("T_Junction.cas.h5", "other_files")

set_config(blocking=True, set_view_on_display="isometric")

User inputs#

Defining user inputs

rom_inputs = {"main_inlet_temperature": 353.15, "side_inlet_temperature": 293.15}
rom_parameters = {
    "ThermalROM23R1_1_colorbar_min": 290,
    "ThermalROM23R1_1_colorbar_max": 360,
    "ThermalROM23R1_1_store_snapshots": 1,
}

Auxiliary functions definition#

Conversion of ROM snapshot for data mapping on CFD mesh.

def snapshot_to_cfd(snapshot_file, geometry_file, field_name, outputFilePath):
    """Create a Fluent Interpolation file that can be loaded in Fluent and map to the CFD mesh. This is an example of
    implementation for a single field of scalar data (e.g. temperature field)
    """

    with open(geometry_file, "rb") as geo, open(snapshot_file, "rb") as snp:
        nb = struct.unpack("Q", snp.read(8))[0]
        struct.unpack("Q", geo.read(8))
        res_list = []
        for i in range(nb):
            res_line = []
            res_line.append(struct.unpack("d", geo.read(8))[0])
            res_line.append(struct.unpack("d", geo.read(8))[0])
            res_line.append(struct.unpack("d", geo.read(8))[0])
            res_line.append(struct.unpack("d", snp.read(8))[0])
            res_list.append(res_line)

    with open(outputFilePath, "w") as ipfile:
        ipfile.write("3\n")  # IP file format
        ipfile.write("3\n")  # 2D or 3D - 3D for now
        ipfile.write(str(len(res_list)) + "\n")  # number of data
        ipfile.write("1\n")  # number of field data
        ipfile.write(field_name + "\n")  # name of field data
        for j in range(0, len(res_list[0])):
            ipfile.write("(")
            for i in range(0, len(res_list)):
                ipfile.write(str(res_list[i][j]) + "\n")
            ipfile.write(")\n")

    return outputFilePath

Loading the Twin Runtime and generate the temperature results from the TBROM#

print("Loading model: {}".format(twin_file))
twin_model = TwinModel(twin_file)

twin_model.initialize_evaluation(inputs=rom_inputs, parameters=rom_parameters)

rom_name = twin_model.tbrom_names[0]
rom_directory = twin_model.get_rom_directory(rom_name)
snapshot = twin_model.get_snapshot_filepath(rom_name)
geometry = twin_model.get_geometry_filepath(rom_name)

temperature_file = snapshot_to_cfd(snapshot, geometry, "temperature", os.path.join(rom_directory, "cfd_file.ip"))
Loading model: C:\Users\ansys\AppData\Local\Temp\TwinExamples\twin_files\ThermalTBROM_23R1_other.twin

Post-processing with image generated by point cloud based ROM Viewer#

view_name = twin_model.get_available_view_names(rom_name)[0]
image_filepath = twin_model.get_image_filepath(rom_name, view_name)
plt.imshow(img.imread(image_filepath))
plt.show()
04 TBROM images

Post-processing with image generated by Fluent#

solver = pyfluent.launch_fluent(precision="double", processor_count=2, mode="solver")
solver.file.read(file_type="case", file_name=cfd_file)
tui = solver.tui
tui.file.interpolate.read_data(temperature_file)
tui.display.objects.display("contour-1")
tui.display.save_picture(os.path.join(rom_directory, f"{view_name}_Fluent_0.000000.png"))

image = img.imread(os.path.join(rom_directory, f"{view_name}_Fluent_0.000000.png"))
plt.imshow(image)
plt.show()
04 TBROM images
Fast-loading "C:\PROGRA~1\ANSYSI~1\v222\fluent\fluent22.2.0\\addons\afd\lib\hdfio.bin"
Done.
Multicore processors detected. Processor affinity set!

Reading from pytwin-win10:"C:\Users\ansys\AppData\Local\Temp\TwinExamples\other_files\T_Junction.cas.h5" in NODE0 mode ...
  Reading mesh ...
      215876 cells,     2 cell zones ...
          76008 mixed cells,  zone id: 4
         139868 tetrahedral cells,  zone id: 5
      518843 faces,    18 face zones ...
            234 mixed wall faces,  zone id: 20
            505 mixed wall faces,  zone id: 19
          26342 mixed wall faces,  zone id: 21
          26342 mixed wall faces,  zone id: 23
            271 triangular wall faces,  zone id: 1
         162380 mixed interior faces,  zone id: 2
         266064 triangular interior faces,  zone id: 3
           6072 triangular interface faces,  zone id: 8
            117 mixed pressure-outlet faces,  zone id: 9
           3222 mixed symmetry faces,  zone id: 10
            117 mixed velocity-inlet faces,  zone id: 11
            104 mixed velocity-inlet faces,  zone id: 12
          14323 triangular wall faces,  zone id: 13
           7129 triangular interface faces,  zone id: 14
           1837 triangular symmetry faces,  zone id: 15
           3650 triangular wall faces,  zone id: 16
             65 triangular wall faces,  zone id: 17
             69 triangular wall faces,  zone id: 18
       55905 nodes,     1 node zone  ...
  Done.

  Reading data for "scenario2" profile.

Building...
     mesh
        auto partitioning mesh by Metis (fast, model-weighted),
        distributing mesh
                pairs..,
                parts..,
                faces..,
                nodes..,
                shadow nodes..,
                cells..,
        bandwidth reduction using Reverse Cuthill-McKee: 49343/1229 = 40.1489
     materials,
     interface,
     domains,
        mixture
     zones,
        wall_hot_end
        wall_cold_end
        wall_adiabatic
        symmetry_solid
        interface_solid_side
        convection
        velocity_inlet_side
        velocity_inlet_main
        symmetry_fluid
        pressure_outlet
        interface_fluid_side
        interior-solid-part_2
        interior-fluid
        wall-solid-part_2
        interface_fluid_side-non-overlapping
        interface_solid_side-non-overlapping
        interface-wall1-1-1
        interface-wall1-1-1-shadow
        solid-part_2
        fluid
     mesh interfaces,
     parallel,

Info: At least one many-to-many mesh interface is found in the case file. Such mesh interfaces will not be available in a future release of Fluent. It is recommended to convert to the current default one-to-one mesh interfaces with the following text command:
/define/mesh-interfaces/one-to-one-pairing? yes

Done.
Reading C:\\Users\\ansys\\AppData\\Local\\Temp\\TwinExamples\\twin_files\\pyTwinWorkingDir\\ThermalTBROM_23R1_other.5ae634c836d64e769169\\ROM_files\\ThermalROM23R1_1\\cfd_file.ip...
Reading IP data ...
        x-coord
        y-coord
        z-coord
        temperature
  Done.
  Initializing values...
  Done.
Note: zone-surface: cannot create surface from sliding interface zone.
Creating empty surface.
Note: zone-surface: cannot create surface from sliding interface zone.
Creating empty surface.
Note: zone-surface: cannot create surface from sliding interface zone.
Creating empty surface.
Note: zone-surface: cannot create surface from sliding interface zone.
Creating empty surface.
Note: zone-surface: cannot create surface from sliding interface zone.
Creating empty surface.
Note: zone-surface: cannot create surface from sliding interface zone.
Creating empty surface.

Post-processing the ROM results in 3D Viewer#

graphics = Graphics(session=solver)
temperature_contour = graphics.Contours["contour-temperature"]
temperature_contour.field = "temperature"
temperature_contour.show_edges = True
temperature_contour.surfaces_list = [
    "convection",
    "interface-side1-wall-interface_fluid_side",
    "interface-side2-wall-interface_solid_side",
    "interface-wall1-1-1",
    "interface-wall1-1-1-shadow",
    "interface_solid_side",
    "symmetry_solid",
    "wall-19",
    "wall-20",
    "wall-solid-part_2",
    "wall_adiabatic",
    "wall_cold_end",
    "wall_hot_end",
]
temperature_contour.display()
../../_images/TBROM_fluent_viewer.png
solver.exit()

Total running time of the script: ( 0 minutes 44.640 seconds)

Gallery generated by Sphinx-Gallery