본문 바로가기

LAMMPS

Domain decomposition VTK convert

LAMMPS에서 load balancing을 하게되면, 시뮬레이션 타임병 load balancing된 domain decomposition 정보가 텍스트 파일로 저장된다. 저장되는 정보는 sub domain의 node와 grid정보이다.

이걸 paraview에서 읽어드릴려면, 변환해 줘야 되는데, 아래와 같이 하면 된다.

 

#!/usr/bin/env python3
import sys

input_filename = "./info.balancing"  # or ./info.balancing, etc.

with open(input_filename, 'r') as f:
    lines = f.readlines()

lines = [ln.strip() for ln in lines]

# We'll store data in a dictionary keyed by timestep value:
#   data_dict[timestep] = {
#       "node_lines": [],
#       "cube_lines": [],
#   }
data_dict = {}

current_ts = None
reading_nodes = False
reading_cubes = False

i = 0
n = len(lines)

while i < n:
    line = lines[i]

    if line.startswith("ITEM: TIMESTEP"):
        # The next line holds the numeric timestep
        i += 1
        ts_val = int(lines[i])  # e.g. "10000" or "20000"
        # Ensure we have an entry in data_dict
        if ts_val not in data_dict:
            data_dict[ts_val] = {
                "node_lines": [],
                "cube_lines": []
            }
        current_ts = ts_val
        reading_nodes = False
        reading_cubes = False

    elif line.startswith("ITEM: NODES"):
        # from here on, lines go to node_lines until next ITEM
        reading_nodes = True
        reading_cubes = False

    elif line.startswith("ITEM: CUBES"):
        # from here on, lines go to cube_lines until next ITEM
        reading_nodes = False
        reading_cubes = True

    elif line.startswith("ITEM:"):
        # Some other "ITEM" (like BOX BOUNDS, NUMBER OF NODES, etc.)
        # We can just ignore or handle if needed
        reading_nodes = False
        reading_cubes = False

    else:
        # It's a data line
        if current_ts is not None:
            if reading_nodes and line:
                data_dict[current_ts]["node_lines"].append(line)
            elif reading_cubes and line:
                data_dict[current_ts]["cube_lines"].append(line)

    i += 1


def write_vtk_for_timestep(ts_val, node_lines, cube_lines):
    """Given node lines and cube lines, write domain_tXXXX.vtk."""
    # Parse node lines -> dictionary of coords
    id_to_coords = {}
    for ln in node_lines:
        # Format: ID  Type  X  Y  Z
        toks = ln.split()
        node_id = int(toks[0])
        x, y, z = float(toks[2]), float(toks[3]), float(toks[4])
        id_to_coords[node_id] = (x, y, z)

    sorted_ids = sorted(id_to_coords.keys())
    id_to_new = {}
    coords_list = []
    for i, old_id in enumerate(sorted_ids):
        id_to_new[old_id] = i
        coords_list.append(id_to_coords[old_id])

    num_points = len(coords_list)

    # Parse cube lines -> list of 8 corners each
    cells = []
    for ln in cube_lines:
        toks = ln.split()
        # skip first two (cubeID, cubeType), read n1..n8
        n1, n2, n3, n4, n5, n6, n7, n8 = map(int, toks[2:10])
        c = [
            id_to_new[n1],
            id_to_new[n2],
            id_to_new[n3],
            id_to_new[n4],
            id_to_new[n5],
            id_to_new[n6],
            id_to_new[n7],
            id_to_new[n8],
        ]
        cells.append(c)

    num_cells = len(cells)
    out_name = f"domain_t{ts_val}.vtk"

    with open(out_name, 'w') as out:
        out.write("# vtk DataFile Version 2.0\n")
        out.write("LAMMPS Domain Decomposition Example\n")
        out.write("ASCII\n")
        out.write("DATASET UNSTRUCTURED_GRID\n")

        # Points
        out.write(f"POINTS {num_points} float\n")
        for (x, y, z) in coords_list:
            out.write(f"{x} {y} {z}\n")

        # Cells
        out.write(f"\nCELLS {num_cells} {num_cells*(8+1)}\n")
        for c in cells:
            out.write("8 " + " ".join(map(str, c)) + "\n")

        # Cell types
        out.write(f"\nCELL_TYPES {num_cells}\n")
        for _ in range(num_cells):
            out.write("12\n")  # 12 = VTK_HEXAHEDRON

    print(f"Wrote {out_name}  (Points={num_points}, Cells={num_cells})")


# Finally, process each timestep in ascending order
for ts_val in sorted(data_dict.keys()):
    node_lines = data_dict[ts_val]["node_lines"]
    cube_lines = data_dict[ts_val]["cube_lines"]

    # If either is empty, you probably have partial data
    # but in your final file you do have both for each TS.
    if not node_lines:
        print(f"WARNING: Timestep {ts_val} has no NODES!")
    if not cube_lines:
        print(f"WARNING: Timestep {ts_val} has no CUBES!")

    write_vtk_for_timestep(ts_val, node_lines, cube_lines)

print("Done.")

 

paraview에서는 Surface with Edge가 볼만 하다.

 

 

 

'LAMMPS' 카테고리의 다른 글

AOCC, AOCL Cmake (optional)  (0) 2025.03.03
IntelOneAPI 환경에서 실행  (0) 2025.02.27
Local patch  (0) 2025.02.20
NUMA Pinning with intelOneAPI  (0) 2025.02.19
wall/gran의 정보 빨아오기  (0) 2025.02.09