///|
/// Semantic labels for boundary patches.
pub(all) enum BoundaryLabel {
Interior
Wall
Inlet
Outlet
Periodic
Obstacle
} derive(Debug, Eq)
///|
/// Row-major boundary label map.
pub(all) struct BoundaryMap {
size : Size
labels : Array[BoundaryLabel]
} derive(Debug)
///|
/// Allocate an interior-filled boundary map.
pub fn BoundaryMap::new(size~ : Size) -> BoundaryMap {
{
size,
labels: Array::make(size.width.max(0) * size.height.max(0), Interior),
}
}
///|
/// Set a boundary label within the map.
pub fn BoundaryMap::set(
self : BoundaryMap,
x~ : Int,
y~ : Int,
label~ : BoundaryLabel,
) -> Unit {
if x >= 0 && y >= 0 && x < self.size.width && y < self.size.height {
self.labels[y * self.size.width + x] = label
}
}
///|
/// Get a label, treating out-of-domain coordinates as walls.
pub fn BoundaryMap::get(
self : BoundaryMap,
x~ : Int,
y~ : Int,
) -> BoundaryLabel {
if x >= 0 && y >= 0 && x < self.size.width && y < self.size.height {
self.labels[y * self.size.width + x]
} else {
Wall
}
}
///|
/// Count one label.
pub fn BoundaryMap::count(self : BoundaryMap, label : BoundaryLabel) -> Int {
let mut result = 0
for current in self.labels {
if current == label {
result += 1
}
}
result
}
///|
/// Count all non-interior labels.
pub fn BoundaryMap::boundary_count(self : BoundaryMap) -> Int {
self.labels.length() - self.count(Interior)
}
///|
/// Convert a label to a stable string.
pub fn boundary_label_name(label : BoundaryLabel) -> String {
match label {
Interior => "interior"
Wall => "wall"
Inlet => "inlet"
Outlet => "outlet"
Periodic => "periodic"
Obstacle => "obstacle"
}
}
///|
/// Export labels as CSV.
pub fn BoundaryMap::to_csv(self : BoundaryMap) -> String {
let builder = StringBuilder(
size_hint=self.size.width * self.size.height * 12 + 16,
)
builder.write_string("x,y,label\n")
for y in 0.. String {
let builder = StringBuilder(
size_hint=(self.size.width + 1) * self.size.height,
)
for y in 0.. '.'
Wall => '#'
Inlet => 'I'
Outlet => 'O'
Periodic => 'P'
Obstacle => 'X'
}
builder.write_char(symbol)
}
builder.write_char('\n')
}
builder.to_string()
}
///|
/// Set the outer frame to wall labels.
pub fn BoundaryMap::set_outer_walls(self : BoundaryMap) -> Unit {
for x in 0.. DomainMask {
let result = DomainMask::new(size=self.size)
for y in 0..