Step 1 — Topology and Cochains
Capability
Construct a small simplicial mesh and allocate a cochain with the correct cardinality.
Problem Statement
Start with the smallest surface mesh where the bookkeeping is still visible. We want a mesh with vertices, edges, and faces, and we want the code to state which cells a 0-form lives on.
Mathematical Idea
A primal 0-form is a discrete scalar field on vertices. Before talking about PDEs, it is worth making the discrete domain and the storage type concrete.
Flux Concepts
Mesh(2, 2)means a 2D simplicial complex embedded in 2D.Cochain(Mesh2D, 0, Primal)means one scalar per vertex.- The cochain length is determined from the mesh, not from a manual size argument.
Minimal Runnable Snippet
Commented walkthrough:
const std = @import("std");
const flux = @import("flux");
pub fn run(allocator: std.mem.Allocator) !void {
const Mesh2D = flux.topology.Mesh(2, 2);
// Build the smallest rectangular triangulation that is still interesting:
// four vertices, five edges, and two oriented faces.
var mesh = try Mesh2D.plane(allocator, 2, 2, 1.0, 1.0);
defer mesh.deinit(allocator);
// A primal 0-cochain stores one scalar per vertex.
var scalar = try flux.forms.Cochain(Mesh2D, 0, flux.forms.Primal).init(allocator, &mesh);
defer scalar.deinit(allocator);
try std.testing.expect(mesh.num_vertices() > 0);
try std.testing.expect(mesh.num_edges() > 0);
try std.testing.expect(mesh.num_faces() > 0);
try std.testing.expectEqual(@as(usize, mesh.num_vertices()), scalar.values.len);
}
test "step 01 commented snippet compiles and runs" {
try run(std.testing.allocator);
}
Plain program:
const std = @import("std");
const flux = @import("flux");
pub fn run(allocator: std.mem.Allocator) !void {
const Mesh2D = flux.topology.Mesh(2, 2);
var mesh = try Mesh2D.plane(allocator, 2, 2, 1.0, 1.0);
defer mesh.deinit(allocator);
var scalar = try flux.forms.Cochain(Mesh2D, 0, flux.forms.Primal).init(allocator, &mesh);
defer scalar.deinit(allocator);
try std.testing.expect(mesh.num_vertices() > 0);
try std.testing.expectEqual(@as(usize, mesh.num_vertices()), scalar.values.len);
}
test "step 01 plain snippet compiles and runs" {
try run(std.testing.allocator);
}
Expected Result
On a 2 x 2 rectangular triangulation, the snippet checks that the mesh cardinalities and cochain
length agree. This is the first shape invariant the type system helps you keep honest.
Possible Extensions
- Change the grid resolution and inspect how the number of edges and faces scales.
- Allocate a primal 1-form and compare its storage length against
mesh.num_edges(). - Read the
MeshAPI before touching any PDE example.
API Reference Jump
See flux.topology.Mesh and
flux.forms.Cochain.