Getting Started

Loading a mesh

load_mesh reads any format the Gmsh SDK can open — .msh (v2.2 and v4), .stl, .step/.stp, Nastran, .med, legacy .vtk, and more. It auto-detects XML VTK (.vtu) files, which are read through ReadVTK.jl, and Nek5000/NekRS .re2 files, which are read by a built-in parser. Meshes may be structured or unstructured, with 1st- or 2nd-order elements (or a mix).

Radiating geometry is partitioned by named groups (Physical Surface in 3D, Physical Curve in 2D). Formats without named groups (e.g. STL) fall back to a single "default" group.

using RadiativeViewFactor

# 3D surface mesh (default)
mesh = load_mesh("geometry.msh")

# 2D planar curve mesh
mesh = load_mesh("planar.msh"; surface_dim=1)

# Other formats are detected from the extension
mesh = load_mesh("part.stl")
mesh = load_mesh("assembly.step")

# XML VTK (.vtu) requires ReadVTK in scope
using ReadVTK
mesh = load_mesh("grid.vtu")

# Nek5000/NekRS mesh: boundary faces of the hex volume mesh
mesh = load_mesh("case.re2")

See Mesh Requirements for supported element types, normal orientation, and format-specific behaviour.

Computing view factors

result = compute_view_factors(mesh; nquad=4)

This returns a ViewFactorResult containing view factors at both the element level (F_elem) and the physical-group level (F_group), along with the element and group areas (A_elem, A_group; lengths for curve meshes). The integration method is chosen by keyword — see Integration Methods:

# Duffy near singularities
compute_view_factors(mesh; nquad=6, use_duffy=true)
# pair-area Monte Carlo
compute_view_factors(mesh; monte_carlo=true, n_samples=5000)
# ray-shooting Monte Carlo
compute_view_factors(mesh; raytrace=true, n_rays=10000)
# with a blocking surface
compute_view_factors(mesh; nquad=4, obstruction_groups=[3])

Reading the result

The rows and columns of F_group correspond to physical groups in the order given by result.group_tags (sorted) and result.group_names:

# Print all group names
println(result.group_names)

# Look up a specific pair by name
i = findfirst(==("hotplate"),  result.group_names)
j = findfirst(==("coldplate"), result.group_names)
println("F(hotplate → coldplate) = ", result.F_group[i, j])

F_group[i, j] is the view factor from group i to group j.

Validation checks

check_reciprocity(result)   # verifies Aᵢ Fᵢⱼ ≈ Aⱼ Fⱼᵢ
check_closure(result)       # verifies no row sum exceeds 1

Both return a Bool and print what they measured (the maximum relative reciprocity error, and the row-sum range). check_closure only fails when a row sum is above 1 (by more than tol); row sums below 1 are expected for open geometries where radiation escapes through open boundaries.

For a closed enclosure, enforce_closure returns a copy of the result whose F_elem satisfies both reciprocity and Σⱼ Fᵢⱼ = 1 to machine precision. This matters when the view factors feed a radiosity solve, because a small row-sum error is multiplied by the (large) radiosity and can swamp a small net flux:

result = enforce_closure(result, mesh)

Do not use it on an open enclosure — including any result computed with radiating_groups — since it would force rows to sum to 1 and invent radiation that is not there.

Computing one pair of surfaces in a crowded mesh

Assembly is dense over whatever it is handed, so a mesh full of shadowing bodies costs O(N_total²) even when only one pair of surfaces is wanted. radiating_groups restricts the radiating set while every group still obstructs:

all_tags = collect(keys(mesh.group_tags))
result = compute_view_factors(mesh; nquad=4,
                              radiating_groups   = [wall_tag, pin_tag],
                              obstruction_groups = all_tags)

The returned F_group covers only the radiating groups, and the enclosure is deliberately open, so use check_reciprocity (not check_closure) to validate it. See Obstruction Detection.

Nek5000/NekRS export

A mesh loaded from a .re2 file remembers each boundary face's Nek (element, face) identity, so its view factors can be written straight back out for the Nek-VF surface-to-surface radiation module:

mesh   = load_mesh("case.re2")
result = compute_view_factors(mesh; nquad=6, use_duffy=true)
result = enforce_closure(result, mesh)   # the enclosure is closed
write_nekrs_view_factors("case.vf", result, mesh)

See write_nekrs_view_factors.