using RayTraceHeatTransfer
using StaticArrays
using GeometryBasics
= RayTraceHeatTransfer.PolyFace2D{Float64}[] # create a vector to hold parts
faces_1
# build the first part
= SVector(
vertices1 Point2(0.0, 0.0), # 2D vertices
Point2(1.0, 0.0),
Point2(1.0, 1.0),
Point2(0.0, 1.0),
)= SVector(true, true, true, true) # all walls are impenetrable
solidWall1 = 1 # number of spectral (wavelength) bins
n_spectral_bins = 1.0 # local absorption coefficient (vector for spectral bins > 1)
kappa = 0.0 # local scattering coefficient (vector for spectral bins > 1)
sigma_s = RayTraceHeatTransfer.PolyFace2D{Float64}(vertices1, solidWall1, n_spectral_bins, kappa, sigma_s)
face1
# set the physical properties and state
= [1000.0, 0.0, 0.0, 0.0] # known wall temperatures
face1.T_in_w = [0.0, 0.0, 0.0, 0.0] # wall fluxes not used when temperature is specified
face1.q_in_w = -1.0 # unknown gas temperature
face1.T_in_g = 0.0 # known gas flux (radiative equilibrium)
face1.q_in_g = [1.0, 1.0, 1.0, 1.0] # wall emissivities
face1.epsilon
push!(faces_1, face1) # push the first part into the vector for meshing
7 Two-dimensional Geometry Setup
7.1 Overview
This chapter introduces the foundation of the approach: creating accurate physical representations of 2D domains. You’ll learn how to build and visualize 2D geometries using RayTraceHeatTransfer.jl, establishing the geometric framework that the analytical methods will operate on. The chapter progresses systematically through increasingly complex geometries:
- Rectangle: The fundamental building block, essential for later validation against analytical solutions
- L-shape: Introduces non-convex geometries and demonstrates geometric complexity
- Star shape: Showcases the flexibility of the approach with intricate boundaries
Each geometry demonstrates how to construct physical domain representations that serve as the foundation for radiative transfer calculations in subsequent chapters.
7.2 What You’ll Learn
- Building accurate physical representations of 2D domains
- Visualizing geometries with working Julia code
- Understanding how geometric complexity affects domain representation
- Preparing geometric foundations for exchange factor calculations and heat transfer solutions
7.3 Concepts
The graph equilibrium approach builds 2D domains from fundamental radiative transfer elements: control volumes and walls (boundaries). Understanding how these elements are constructed and connected forms the foundation for all subsequent radiative transfer calculations.
Domain Elements
- Control volumes: Represent participating media regions with size given by 4βV (m²), where β is the extinction coefficient and V is the volume
- Walls/boundaries: Represent surfaces with area A (m²) that can emit, absorb, and reflect radiation
- Each element receives a unique incremental number for exchange factor indexing
Radiative Connectivity
Visibility between elements determines radiative exchange and will be calculated through ray tracing in later chapters. Since this method uses Monte Carlo ray tracing rather than angular discretization, it achieves accurate visibility knowledge without directional approximations, enabling analytical solutions that closely represent the true physical domain.
Geometric Construction
Domains are built from convex blocks - either triangles or quadrilaterals - that can be efficiently ray traced. The meshing and ray tracing algorithms handle both geometric primitives seamlessly. Blocks are combined by specifying which walls are ‘solid’ (opaque boundaries) versus ‘penetrable’ (allowing radiation passage between blocks). This modular approach enables complex geometries while maintaining computational efficiency.
Property Assignment
Material properties (known temperature/flux, emissivity, albedo) are assigned during geometry construction using nested inheritance - each mesh element inherits properties from its parent ‘superpiece’. This simplifies property specification compared to defining properties for individual sub-elements while maintaining flexibility through multiple superpieces with different properties.
Visualization and Access
The visualization system displays element numbers, allowing easy identification of specific walls and volumes for result analysis and validation.
7.4 Examples
Now we’ll build three increasingly complex 2D geometries using RayTraceHeatTransfer.jl, starting with the fundamental rectangle that will serve as our validation benchmark.
7.4.1 Rectangle Domain
The rectangle is the most basic geometry and provides an essential validation case since analytical solutions exist for rectangular enclosures. Let’s construct a simple rectangular domain:
Next, the domain is meshed into a desired resolution:
= 11 # splits in (x,y) directions
Ndim = RayTraceHeatTransfer.RayTracingMeshOptim(faces_1, [(Ndim,Ndim)]); mesh1
Finally, the domain is displayed using Makie:
using CairoMakie
activate!()
CairoMakie.inline!(true)
Makie.= Figure(; size = (800, 600))
fig = Axis(fig[1, 1], aspect=AxisAspect(1))
ax plotMesh2D(ax, mesh1) # plot the mesh
RayTraceHeatTransfer.# save("rectangle_mesh.png", fig) # Save the figure
fig
2D quadrilateral mesh
7.4.2 L-shaped Domain
The L-shaped domain is the first non-convex geometry and provides a more complex enclosure, when compared to the rectangle. Let’s construct a simple L-shaped domain. We’ll build it from 3 rectangles:
using RayTraceHeatTransfer
using StaticArrays
using GeometryBasics
= RayTraceHeatTransfer.PolyFace2D{Float64}[] # create a vector to hold parts faces_2
Rectangle 1
# build the first part
= SVector(
vertices1 Point2(0.0, 0.0), # 2D vertices
Point2(1.0, 0.0),
Point2(1.0, 1.0),
Point2(0.0, 1.0),
)= SVector(true, true, false, true) # top wall is open
solidWall1 = RayTraceHeatTransfer.PolyFace2D{Float64}(vertices1, solidWall1, n_spectral_bins, kappa, sigma_s)
face1
# set the physical properties and state
= [1000.0, 0.0, 0.0, 0.0] # known wall temperatures
face1.T_in_w = [0.0, 0.0, 0.0, 0.0] # wall fluxes not used when temperature is specified
face1.q_in_w = -1.0 # unknown gas temperature
face1.T_in_g = 0.0 # known gas flux (radiative equilibrium)
face1.q_in_g = [1.0, 1.0, 1.0, 1.0] # wall emissivities
face1.epsilon
push!(faces_2, face1) # push the first part into the vector for meshing
Rectangle 2
# build the first part
= SVector(
vertices2 Point2(0.0, 1.0), # 2D vertices
Point2(1.0, 1.0),
Point2(1.0, 2.0),
Point2(0.0, 2.0),
)= SVector(false, false, true, true) # two walls are open
solidWall2 = RayTraceHeatTransfer.PolyFace2D{Float64}(vertices2, solidWall2, n_spectral_bins, kappa, sigma_s)
face2
# set the physical properties and state
= [0.0, 0.0, 0.0, 0.0] # known wall temperatures
face2.T_in_w = [0.0, 0.0, 0.0, 0.0] # wall fluxes not used when temperature is specified
face2.q_in_w = -1.0 # unknown gas temperature
face2.T_in_g = 0.0 # known gas flux (radiative equilibrium)
face2.q_in_g = [1.0, 1.0, 1.0, 1.0] # wall emissivities
face2.epsilon
push!(faces_2, face2) # push the second part into the vector for meshing
Rectangle 3
# build the first part
= SVector(
vertices3 Point2(1.0, 1.0), # 2D vertices
Point2(2.0, 1.0),
Point2(2.0, 2.0),
Point2(1.0, 2.0),
)= SVector(true, true, true, false) # two walls are open
solidWall3 = RayTraceHeatTransfer.PolyFace2D{Float64}(vertices3, solidWall3, n_spectral_bins, kappa, sigma_s)
face3
# set the physical properties and state
= [0.0, 0.0, 0.0, 0.0] # known wall temperatures
face3.T_in_w = [0.0, 0.0, 0.0, 0.0] # wall fluxes not used when temperature is specified
face3.q_in_w = -1.0 # unknown gas temperature
face3.T_in_g = 0.0 # known gas flux (radiative equilibrium)
face3.q_in_g = [1.0, 1.0, 1.0, 1.0] # wall emissivities
face3.epsilon
push!(faces_2, face3) # push the second part into the vector for meshing
Next, the domain is meshed into a desired resolution:
= 11 # splits in 3 (x,y) directions
Ndim = RayTraceHeatTransfer.RayTracingMeshOptim(faces_2, [(Ndim,Ndim),(Ndim,Ndim),(Ndim,Ndim)]); mesh2
Finally, the domain is displayed using Makie:
= Figure(; size = (800, 600))
fig = Axis(fig[1, 1], aspect=AxisAspect(1))
ax plotMesh2D(ax, mesh2) # plot the mesh
RayTraceHeatTransfer.# save("L-shaped_mesh.png", fig) # Save the figure
fig
2D L-shaped mesh
7.4.3 Star-shaped Domain
The star-shaped domain is the first non-convex, complex enclosure we’ll mesh programmatically. We’ll build it from 10 triangles. First, let’s calculate the points of the star:
using RayTraceHeatTransfer
using GeometryBasics
using StaticArrays
# Inner pentagon radius and outer star point radius
= 0.3
inner_radius = 1.0
outer_radius
# Generate 5 points for pentagon (72° between points)
= Vector{Point2{Float64}}()
inner_points for i in 1:5
= 2π/5 * (i-1) - π/2 # Start from top (-π/2)
angle = inner_radius * cos(angle)
x = inner_radius * sin(angle)
y push!(inner_points, Point2(x, y))
end
# Generate 5 outer star points
= Vector{Point2{Float64}}()
outer_points for i in 1:5
= 2π/5 * (i-1) - π/2 + π/5 # Offset by half pentagon angle
angle = outer_radius * cos(angle)
x = outer_radius * sin(angle)
y push!(outer_points, Point2(x, y))
end
Next, let’s create the faces:
# Create faces
= PolyFace2D{Float64}[]
faces_1
# Central pentagon (can be divided into triangles)
for i in 1:5
= SVector(
vertices Point2(0.0, 0.0), # Center
inner_points[i],mod1(i+1, 5)]
inner_points[
)= SVector(false, false, false)
solidWalls = PolyFace2D{Float64}(vertices, solidWalls, n_spectral_bins, kappa, sigma_s)
face = [0.0, 0.0, 0.0]
face.T_in_w = [0.0, 0.0, 0.0]
face.q_in_w = -1.0
face.T_in_g = 1000.0
face.q_in_g = [1.0, 1.0, 1.0]
face.epsilon
push!(faces_1, face)
end
# Star points (triangles)
for i in 1:5
= SVector(
vertices
inner_points[i],
outer_points[i],mod1(i+1, 5)]
inner_points[
)= SVector(true, true, false)
solidWalls = PolyFace2D{Float64}(vertices, solidWalls, n_spectral_bins, kappa, sigma_s)
face = [0.0, 0.0, 0.0]
face.T_in_w = [0.0, 0.0, 0.0]
face.q_in_w = -1.0
face.T_in_g = 1000.0
face.q_in_g = [1.0, 1.0, 1.0]
face.epsilon
push!(faces_1, face)
end
Finally, let’s mesh and plot the geometry:
= 11
Ndim = RayTracingMeshOptim(faces_1, [(Ndim,Ndim),(Ndim,Ndim),(Ndim,Ndim),(Ndim,Ndim),(Ndim,Ndim),
mesh1 (Ndim,Ndim),(Ndim,Ndim),(Ndim,Ndim),(Ndim,Ndim),(Ndim,Ndim)]);
using CairoMakie
activate!()
CairoMakie.inline!(true)
Makie.= Figure(; size = (800, 600))
fig = Axis(fig[1, 1], aspect=AxisAspect(1))
ax plotMesh2D(ax, mesh1) # plot the mesh
RayTraceHeatTransfer.# save("Star-shaped_mesh.png", fig) # Save the figure
fig
2D star-shaped mesh