///|
pub(all) struct Grid1D {
cells : Int
length : Double
dx : Double
} derive(Debug, ToJson)
///|
pub fn Grid1D::new(cells : Int, length : Double) -> Grid1D {
{ cells, length, dx: length / cells.to_double() }
}
///|
pub fn Grid1D::cells_count(grid : Grid1D) -> Int {
grid.cells
}
///|
pub fn Grid1D::domain_length(grid : Grid1D) -> Double {
grid.length
}
///|
pub fn Grid1D::cell_width(grid : Grid1D) -> Double {
grid.dx
}
///|
pub fn Grid1D::is_valid(grid : Grid1D) -> Bool {
grid.cells > 0 && grid.length > 0.0 && grid.dx > 0.0
}
///|
pub fn Grid1D::cell_index(grid : Grid1D, x : Double) -> Int {
periodic_index(@math.floor(grid.wrap(x) / grid.dx).to_int(), grid.cells)
}
///|
pub fn Grid1D::position(grid : Grid1D, index : Int) -> Double {
(index.to_double() + 0.5) * grid.dx
}
///|
pub fn Grid1D::wrap(grid : Grid1D, x : Double) -> Double {
let periods = @math.floor(x / grid.length)
let y = x - periods * grid.length
if y < 0.0 {
y + grid.length
} else if y >= grid.length {
y - grid.length
} else {
y
}
}
///|
pub fn zeros(n : Int) -> Array[Double] {
Array::make(n, 0.0)
}
///|
pub fn mean(values : ArrayView[Double]) -> Double {
if values.length() == 0 {
0.0
} else {
values.fold(init=0.0, (acc, v) => acc + v) / values.length().to_double()
}
}
///|
pub fn l2_norm(values : ArrayView[Double]) -> Double {
values.fold(init=0.0, (acc, v) => acc + v * v).sqrt()
}
///|
pub fn linspace(start : Double, stop : Double, count : Int) -> Array[Double] {
if count <= 1 {
[start]
} else {
let step = (stop - start) / (count - 1).to_double()
Array::makei(count, fn(i) { start + i.to_double() * step })
}
}