C Supplementary Material 3

C.1 Additional Results

(a) \( 19456/4849\approx 4 \)

   

(b) \( 71424/6221\approx 11 \)

   

(c) \( 273664/8048\approx 34 \)

Figure C.1: Sparse set of triangles (black) for \( T=0 \), analog to Figure 6.4 in Chapter 6.

(a) \( 17840/3349\approx 5 \)

   

(b) \( 64908/4717\approx 14 \)

   

(c) \( 247892/7768\approx 32 \)

Figure C.2: Sparse set of triangles (black) for \( T=3 \), analog to Figure 6.4 in Chapter 6.

(a) direct flux, initial geometry

(b) \( d_{max}=16 \)


(c) \( d_{max}=8 \)

(d) \( d_{max}=4 \)


(e) \( d_{max}=2 \)

(f) \( d_{max}=1 \)

Figure C.3: Results for each iteration of the partitioning scheme (\( d_{max_0}=16 \)) for the geometry introduced in Figure 6.1. (a) Direct flux on the initial geometry. (b) Initial sparse set (including the material interfaces). (c)- (f) Results for the iterations \( d_{max}=8 \) to \( d_{max}=1 \).

C.2 Algorithm Subroutines

Function FlagNeighborhood(\( i \), \( i_{parent} \), \( i_{prev} \), \( d_{path} \), \( d_{max} \)):

\( d_{max_{local}} \) = distTarget[\( i \)];

if withdrawn[i] AND \( d_{max} >= d_{path} \) AND \( d_{max_{local}} > d_{path} \) AND \( distance[i] > d_{path} \) then

touched[i] = true;

parent[i] = \( i_{parent} \);

distance[i] = \( d_{path} \);

foreach \( i_{ne} \) in edgeNeighbors[\( i \)] do

if \( i_{ne} != i_{prev} \) then

FlagNeighborhood(\( i_{ne} \), \( i_{parent} \), \( i \), \( d_{path} \) + 1, \( d_{max} \))

else

SetNeighbors(\( i \), \( i_{parent} \));

Function FlagTriangles(indices, \( d_{max} \)):

touched[] = false;

\( d_{path} \) = 0;

numNewPatches = 0;

foreach \( i \) in indices do

if !touched[i] and withdrawn[i] then

++numNewPatches;

active[i] = touched[i] = reflagged[i] = true;

parent[i] = i;

distance[i] = \( d_{path} \);

foreach \( i_{ne} \) in edgeNeighbors[\( i \)] do

FlagNeighborhood(\( i_{ne} \), \( i \), \( i \), \( d_{path} \) + 1, \( d_{max} \))

return numNewPatches

Function RefinePatch(\( i_{active} \), \( d_{max} \)):

count = Withdraw(\( i_{active} \), \( d_{max} / 2 \))

if count == 0 then

return 0

else

UnSetAllNeighbors(\( i_{active} \))

numNewPatches = FlagTriangles(patches[\( i_{active} \)].patchIndices, \( d_{max} \))

RebuildNeighbors(\( i_{active} \))

UnWithdraw(\( i_{active} \))

return numNewPatches

Algorithm 3: Recursive flagging and refinement of patches.

Function SetNeighbors(\( i \), \( i_{active} \)):

if parent[i] != \( -1 \) and parent[i] != \( i_{active} \) then

sparseNeighbors[parent[\( i \)]].insert(\( i_{active} \));

sparseNeighbors[\( i_{active} \)].insert(parent[\( i \)]);

Function UnSetAllNeighbors(\( i_{active} \)):

foreach \( i_{ns} \) in sparseNeighbors[\( i_{active} \)].activeNeighbors do

sparseNeighbors[\( i_{ns} \)].erase(\( i_{active} \));

sparseNeighbors[\( i_{active} \)].erase(\( i_{ns} \));

Function RebuildNeighbors(\( i_{active} \)):

foreach \( i \) in patches[\( i_{active} \)].patchIndices do

if \( !withdrawn[i] \) then

foreach \( i_{ne} \) in edgeNeighbors[\( i \)] do

SetNeighbors(\( i_{ne} \), \( i_{active} \));

Algorithm 4: Helper functions for sparse neighbor handling.

Function Withdraw(\( i_{active} \), \( d_{} \)):

count = 0;

foreach \( i \) in patches[\( i_{active} \)].patchIndices do

if \( distance[i] > d_{} \) then

withdrawn[i] = true;

distance[i] = \( d_{max_0} \);

parent[i] = -1;

++count;

return count

Function UnWithdraw(\( i_{active} \)):

foreach \( i \) in patches[\( i_{active} \)].patchIndices do

withdrawn[i] = false;

Function RebuildPatches():

patches.clear();

for \( i = 0\ldots N_{tri}-1 \) do

if parent[i] == -1 then

patches[parent[i]].insert(i);

Algorithm 5: Helper functions for withdrawal and building patch
information.