Skip to content

Add wall heat load visualization and port placement optimization #284

@krystophny

Description

@krystophny

Summary

Add a Python-based engineering optimization workflow for alpha particle wall heat loads: visualization of heat flux on wall geometry and optimization of port/component placement to minimize thermal exposure.

Motivation

Computing wall loads is not novel (ASCOT, BEAMS3D do this). The value-add is:

  1. Fast computation for optimization loops - SIMPLE's symplectic methods
  2. Engineering design tool - from heat map to port placement
  3. Integrated workflow - one package from alpha birth to engineering output

Prerequisites (Simplified!)

Using chartmap-based wall tracing (no CGAL needed):

Architecture

┌─────────────────────────────────────────────────────────┐
│  pysimple.engineering                                   │
│  ├── WallHeatMap        - heat flux on (theta,zeta) grid│
│  ├── PortOptimizer      - placement optimization        │
│  ├── visualization      - PyVista-based 3D plots        │
│  └── export             - VTK, ParaView, reports        │
└─────────────────────────────────────────────────────────┘
         │
         ▼
┌─────────────────────────────────────────────────────────┐
│  SIMPLE output (times_lost.dat or wall_hits.nc)        │
│  └── Per-particle: theta, zeta, x, y, z, time, energy  │
└─────────────────────────────────────────────────────────┘

Implementation

1. Wall Heat Map (from chartmap coordinates)

from pysimple.engineering import WallHeatMap

# Load SIMPLE output + chartmap for coordinate conversion
heat_map = WallHeatMap.from_simple_output(
    chartmap_file="wall.chartmap.nc",
    times_lost_file="times_lost.dat",  # or wall_hits.nc
    particle_energy=3.5e6,  # eV
    n_particles=10000,
    trace_time=0.1  # s
)

# Bin by (theta, zeta) on wall surface
heat_map.n_theta_bins = 64
heat_map.n_zeta_bins = 128

# Properties
heat_map.total_power          # MW
heat_map.peak_flux            # MW/m²
heat_map.flux_grid            # 2D array [theta, zeta] → MW/m²

2. Port Placement Optimizer

from pysimple.engineering import PortOptimizer

opt = PortOptimizer(heat_map)

# Define ports (in theta, zeta coordinates)
opt.add_port(name="NBI_1", theta_width=0.3, zeta_width=0.2)
opt.add_port(name="diag_1", theta_width=0.1, zeta_width=0.1)

# Constraints  
opt.set_max_flux_on_port(0.5)  # MW/m²
opt.add_exclusion_zone(theta_range=(0, 0.3))  # near divertor

# Solve
result = opt.solve(method='differential_evolution')
print(result.port_positions)  # dict: name → (theta_center, zeta_center)

3. Visualization (PyVista)

from pysimple.engineering import visualization as viz

# Convert (theta, zeta) grid to 3D surface via chartmap
surface = viz.create_wall_surface(heat_map.chartmap_file)
surface["heat_flux"] = heat_map.flux_grid.flatten()

# Plot
plotter = viz.plot_wall_heat_flux(surface, cmap='hot', clim=[0, 10])
viz.add_ports(plotter, result.port_positions, heat_map.chartmap_file)
plotter.show()

# Export
surface.save("wall_with_loads.vtk")

Dependencies (Minimal)

[project.optional-dependencies]
engineering = [
    "pyvista>=0.43",      # visualization
    "scipy>=1.10",        # optimization  
    "numpy>=1.24",
]

No CGAL, no SIMSOPT, no trimesh required.

Workflow Summary

1. Generate chartmap with wall boundary
   libneo-write-chartmap from-vmec wout.nc wall.chartmap.nc --boundary-offset 0.2

2. Run SIMPLE
   coord_input = "wall.chartmap.nc"
   → outputs times_lost.dat with (theta, zeta) at rho=1

3. Post-process in Python
   heat_map = WallHeatMap.from_simple_output(...)
   result = PortOptimizer(heat_map).solve()
   viz.plot_wall_heat_flux(...)

Related Issues

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions