# Use the existing connected PyFluent variable solver.
task_directory = r"C:\Users\13977\AppData\Local\FluentAGI\data\runs\20261018-131546-79cdb4"
settings = solver.settings
transcript_started = False

gmsh_code = """
gmsh.model.add("half_open_gate_valve")
occ = gmsh.model.occ
coordinates = [
    [0.0, 0.0],
    [0.12, 0.0],
    [0.12, 0.02],
    [0.053, 0.02],
    [0.053, 0.01],
    [0.05, 0.01],
    [0.05, 0.02],
    [0.0, 0.02],
]
points = []
for x, y in coordinates:
    points.append(occ.addPoint(x, y, 0.0))
lines = []
for i in range(len(points)):
    lines.append(occ.addLine(points[i], points[(i + 1) % len(points)]))
loop = occ.addCurveLoop(lines)
fluid = occ.addPlaneSurface([loop])
occ.synchronize()

for name, curves in [
    ("inlet", [lines[7]]),
    ("outlet", [lines[1]]),
    ("walls", [lines[i] for i in [0, 2, 3, 4, 5, 6]]),
]:
    tag = gmsh.model.addPhysicalGroup(1, curves)
    gmsh.model.setPhysicalName(1, tag, name)
tag = gmsh.model.addPhysicalGroup(2, [fluid])
gmsh.model.setPhysicalName(2, tag, "fluid")

distance = gmsh.model.mesh.field.add("Distance")
gmsh.model.mesh.field.setNumbers(
    distance, "CurvesList", [lines[3], lines[4], lines[5]]
)
gmsh.model.mesh.field.setNumber(distance, "Sampling", 100)
near = gmsh.model.mesh.field.add("Threshold")
for key, value in [
    ("InField", distance),
    ("SizeMin", 0.00035),
    ("SizeMax", 0.002),
    ("DistMin", 0.002),
    ("DistMax", 0.015),
]:
    gmsh.model.mesh.field.setNumber(near, key, value)

wake = gmsh.model.mesh.field.add("Box")
for key, value in [
    ("VIn", 0.0008), ("VOut", 0.002),
    ("XMin", 0.045), ("XMax", 0.09),
    ("YMin", 0.0), ("YMax", 0.02),
    ("ZMin", -0.001), ("ZMax", 0.001),
    ("Thickness", 0.005),
]:
    gmsh.model.mesh.field.setNumber(wake, key, value)
combined = gmsh.model.mesh.field.add("Min")
gmsh.model.mesh.field.setNumbers(combined, "FieldsList", [near, wake])
gmsh.model.mesh.field.setAsBackgroundMesh(combined)
for key, value in [
    ("Mesh.MeshSizeFromPoints", 0),
    ("Mesh.MeshSizeFromCurvature", 0),
    ("Mesh.MeshSizeExtendFromBoundary", 0),
    ("Mesh.MeshSizeMin", 0.00035),
    ("Mesh.MeshSizeMax", 0.002),
    ("Mesh.ElementOrder", 1),
    ("Mesh.Algorithm", 6),
]:
    gmsh.option.setNumber(key, value)
gmsh.write(output_dir + "/half_open_gate_valve.step")
gmsh.model.mesh.generate(2)
gmsh.model.mesh.optimize("Relocate2D")
"""

try:
    settings.file.start_transcript(
        file_name=task_directory + r"\gate_valve.trn"
    )
    transcript_started = True

    if settings.setup.models.is_active():
        print("PREVIOUS_MODELS", settings.setup.models.get_state())
        settings.file.write_case_data(
            file_name=task_directory + r"\previous_airfoil_backup.cas.h5"
        )

    mesh = fluentagi.geometry_mesh(
        directory=task_directory,
        code=gmsh_code,
    )
    print("VALVE_MESH", mesh)
    settings.file.read_mesh(file_name=mesh["mesh_file"])
    settings.mesh.check()

    if not settings.setup.models.is_active():
        raise RuntimeError("阀门网格读取后模型未激活。")

    settings.setup.general.solver.type = "pressure-based"
    settings.setup.general.solver.time = "steady"
    settings.setup.models.viscous.model = "laminar"
    settings.setup.models.energy.enabled = False
    settings.setup.general.operating_conditions.gravity.enable = False

    air = settings.setup.materials.fluid["air"]
    air.density.set_state({"option": "constant", "value": 1.225})
    air.viscosity.set_state({"option": "constant", "value": 1.7894e-5})
    print("AIR_READBACK", air.get_state())

    zones = settings.setup.cell_zone_conditions.fluid
    names = zones.get_object_names()
    if not names:
        raise RuntimeError("没有流体单元区。")
    for name in names:
        zones[name].general.material = "air"

    boundaries = settings.setup.boundary_conditions
    inlet = boundaries.velocity_inlet["inlet"]
    inlet.momentum.velocity_specification_method = "Magnitude, Normal to Boundary"
    inlet.momentum.velocity.set_state({"option": "value", "value": 0.05})
    outlet = boundaries.pressure_outlet["outlet"]
    outlet.momentum.gauge_pressure.set_state(
        {"option": "value", "value": 0.0}
    )

    walls = boundaries.wall
    for name in walls.get_object_names():
        wall = walls[name]
        wall.momentum.wall_motion = "Stationary Wall"
        wall.momentum.shear_condition = "No Slip"
        print("WALL_READBACK", name, wall.get_state())

    velocity_state = inlet.momentum.velocity.get_state()
    pressure_state = outlet.momentum.gauge_pressure.get_state()
    print("INLET_READBACK", velocity_state)
    print("OUTLET_READBACK", pressure_state)
    if abs(velocity_state["value"] - 0.05) > 1e-10:
        raise RuntimeError("入口速度读回不符。")
    if abs(pressure_state["value"]) > 1e-10:
        raise RuntimeError("出口表压读回不符。")

    print("DEMO_PARAMETERS", {
        "geometry": "2D half-open gate valve",
        "length_m": 0.12,
        "channel_height_m": 0.02,
        "gate_thickness_m": 0.003,
        "opening_m": 0.01,
        "inlet_speed_m_s": 0.05,
        "Re_based_on_height": 1.225 * 0.05 * 0.02 / 1.7894e-5,
        "refinement": "prescribed gate-distance and downstream box fields",
    })
    print("RESIDUAL_SETTINGS", settings.solution.monitor.residual.get_state())

    settings.file.write_case(
        file_name=task_directory + r"\gate_valve_configured.cas.h5"
    )
    settings.solution.initialization.hybrid_initialize()

    for batch in range(1, 4):
        print("BATCH_BEGIN", batch, "MAX_ITERATIONS", 100)
        settings.solution.run_calculation.iterate(iter_count=100)
        print("BATCH_END", batch)
        settings.file.write_case_data(
            file_name=task_directory
            + r"\gate_valve_batch_"
            + str(batch)
            + ".cas.h5"
        )

    settings.file.write_case_data(
        file_name=task_directory + r"\gate_valve_final.cas.h5"
    )
    exports = fluentagi.export_results(
        directory=task_directory,
        fields=["pressure", "velocity-magnitude"],
    )
    print("EXPORT_RESULTS", exports)
    print(
        "二维固定半开闸阀低雷诺数演示；"
        "局部网格为预设空间加密。"
        "实际收敛以 gate_valve.trn 的残差和收敛提示为依据；"
        "导出以返回文件列表和错误信息为依据。"
    )

finally:
    if transcript_started:
        settings.file.stop_transcript()