Grid Function I/O
Saving and loading grid functions in Rodin.
Introduction
Grid functions represent the discrete solution of a finite element problem. They associate numerical values (degrees of freedom) with a finite element space. Saving and loading grid functions is essential for:
- Storing computed solutions
- Post-processing and visualization
- Checkpoint/restart of simulations
- Transferring data between different analyses
Saving Grid Functions
MFEM Format
The MFEM format stores grid functions as text files:
#include <Rodin/Geometry.h> #include <Rodin/Variational.h> using namespace Rodin; using namespace Rodin::Geometry; using namespace Rodin::Variational; int main() { Mesh mesh; mesh = mesh.UniformGrid(Polytope::Type::Triangle, {16, 16}); P1 Vh(mesh); GridFunction u(Vh); u = [](const Geometry::Point& p) { return p.x() * p.y(); }; // Save grid function and mesh u.save("solution.gf", IO::FileFormat::MFEM); mesh.save("mesh.mesh", IO::FileFormat::MFEM); return 0; }
XDMF Format (Recommended)
For visualization, the XDMF format is recommended. It stores both mesh and field data together and can be opened directly in ParaView:
#include <Rodin/IO/XDMF.h> // After computing the solution... IO::XDMF xdmf("Output"); xdmf.grid().setMesh(mesh).add("solution", u); xdmf.write();
Loading Grid Functions
From MFEM Format
To load a grid function from MFEM format, you need the mesh and finite element space already set up:
// Load mesh Mesh mesh; mesh.load("mesh.mesh", IO::FileFormat::MFEM); // Create FE space on loaded mesh P1 Vh(mesh); // Load grid function GridFunction u(Vh); u.load("solution.gf", IO::FileFormat::MFEM);
Format Coverage
Grid function I/O coverage depends on the role of the format:
| Format | Tested grid function role |
|---|---|
| MFEM | P0, P1, and H1 finite element grid functions |
| MEDIT | Vertex-based solution files (SolAtVertices) |
| HDF5 | Raw degree-of-freedom persistence |
| XDMF | Evaluated visualization attributes |
MFEM H1 grid functions are tested against fixture files generated by MFEM for degrees K = 1, 2, 3, 4, 5, 6, for scalar and vector data, and for both MFEM vector orderings. P0 scalar grid functions are tested on Point, Segment, Triangle, Quadrilateral, Tetrahedron, Hexahedron, and Wedge meshes. P1 and H1 vector grid functions use the vector finite element spaces provided by Rodin; P0 currently exposes a scalar finite element space even though vector P0 elements exist internally.
Multiple Fields
When dealing with multiple fields, you can export them all in one XDMF file:
IO::XDMF xdmf("MultiField"); auto grid = xdmf.grid(); grid.setMesh(mesh); grid.add("temperature", temperature); grid.add("velocity", velocity); grid.add("pressure", pressure); xdmf.write();
All fields will be available for selection in ParaView.
Vector-Valued Fields
Vector-valued grid functions are defined on finite element spaces with multiple components:
// Create a vector P1 space (2 components) P1 Vh(mesh, 2); GridFunction velocity(Vh); velocity = [](const Geometry::Point& p) { return Math::Vector<Real>{{ -p.y(), p.x() }}; }; IO::XDMF xdmf("VectorField"); xdmf.grid().setMesh(mesh).add("velocity", velocity); xdmf.write();