///|
/// Export a scalar field as an ASCII PPM image.
pub fn Field2D::to_ppm(self : Field2D) -> String {
let stats = self.statistics()
let denominator = if stats.maximum == stats.minimum {
1.0
} else {
stats.maximum - stats.minimum
}
let builder = StringBuilder(
size_hint=self.size.width * self.size.height * 12 + 32,
)
builder.write_string("P3\n\{self.size.width} \{self.size.height}\n255\n")
for y in 0.. String {
let builder = StringBuilder(
size_hint=self.size.width * self.size.height * 20 + 256,
)
builder.write_string("# vtk DataFile Version 3.0\n")
builder.write_string("moonbit-lbm field\nASCII\nDATASET STRUCTURED_POINTS\n")
builder.write_string("DIMENSIONS \{self.size.width} \{self.size.height} 1\n")
builder.write_string("ORIGIN 0 0 0\nSPACING 1 1 1\n")
builder.write_string("POINT_DATA \{self.size.width * self.size.height}\n")
builder.write_string("SCALARS \{name} double 1\nLOOKUP_TABLE default\n")
for value in self.data {
builder.write_string("\{value}\n")
}
builder.to_string()
}
///|
/// Export a vector field as CSV.
pub fn VectorField2D::to_csv(self : VectorField2D) -> String {
let builder = StringBuilder(
size_hint=self.size.width * self.size.height * 24 + 24,
)
builder.write_string("x,y,ux,uy,speed\n")
for y in 0.. String {
let builder = StringBuilder(size_hint=self.samples.length() * 40 + 2)
builder.write_char('[')
for i, sample in self.samples {
if i > 0 {
builder.write_char(',')
}
builder.write_string(
"{\"step\":\{sample.step},\"residual\":\{sample.residual},\"mass\":\{sample.mass}}",
)
}
builder.write_char(']')
builder.to_string()
}