Skip to content

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 Mesh API before touching any PDE example.

API Reference Jump

See flux.topology.Mesh and flux.forms.Cochain.