Algorithmic Functions
Overview
The algorithmic module provides advanced numerical algorithms that operate on meshes.
The primary algorithm is HarmonicDiffusion, which solves the Laplace equation
on triangulated surfaces using iterative relaxation. This is useful for smoothly interpolating
sparse constraints across a mesh, such as boundary conditions, temperature fields, or
displacement constraints.
HarmonicDiffusion
template <size_t N>
class HarmonicDiffusion {
public:
// Constructor: takes a mesh and an initial value for all nodes
HarmonicDiffusion(const Mesh<N> &mesh, double init_value = 0.0);
// Solver parameters
void setMaxIter(size_t max_iterations); // Default: 10000
void setEps(double epsilon); // Convergence tolerance (default: 1e-6)
void setEpsilon(double epsilon); // Alias for setEps
// Add a constraint: fix the value at a specific vertex
void addConstraint(uint32_t vertex_index, double value);
// Constrain all border nodes to a given value
void constrainBorders(double value);
// Solve the Laplace equation and return the solution
Serie<double> solve();
};
The harmonic diffusion solver iteratively relaxes the solution toward the Laplace equation (zero second derivative) on the mesh surface. At each iteration, each unconstrained node is updated to the average of its neighbors' values. The process converges when the maximum change between iterations falls below the specified tolerance (epsilon).
Basic Usage
#include <dataframe/geo/mesh.h>
#include <dataframe/algo/harmonic_diffusion.h>
// Create or load a mesh
df::Mesh3D mesh(vertices, triangles);
// Create solver with initial value 0
df::HarmonicDiffusion<3> solver(mesh, 0.0);
// Set solver parameters
solver.setMaxIter(5000);
solver.setEps(1e-8);
// Fix values at specific vertices
solver.addConstraint(0, 100.0); // Vertex 0 = 100
solver.addConstraint(50, 0.0); // Vertex 50 = 0
solver.addConstraint(100, 50.0); // Vertex 100 = 50
// Solve
auto result = solver.solve();
// result is a Serie<double> with smoothly interpolated values
Border Constraints
// Heat diffusion: fix borders to 0, internal source to 100
df::HarmonicDiffusion<3> heat_solver(mesh, 0.0);
// Fix all border nodes to 0 (cold boundary)
heat_solver.constrainBorders(0.0);
// Add a hot spot in the interior
heat_solver.addConstraint(center_vertex_id, 100.0);
heat_solver.setMaxIter(10000);
heat_solver.setEps(1e-6);
auto temperature = heat_solver.solve();
// Add result as mesh attribute
mesh.addVertexAttribute("temperature", temperature);
Complete Example
#include <dataframe/Serie.h>
#include <dataframe/geo/mesh.h>
#include <dataframe/geo/geometry.h>
#include <dataframe/algo/harmonic_diffusion.h>
#include <iostream>
int main() {
// Generate a sphere mesh
auto [verts, tris] = df::geo::generateSphere(4, 1.0);
df::Mesh3D sphere(verts, tris);
// Create harmonic diffusion solver
df::HarmonicDiffusion<3> solver(sphere, 0.5);
solver.setMaxIter(20000);
solver.setEps(1e-8);
// Find the north and south pole vertices (max/min z)
size_t north_pole = 0, south_pole = 0;
double max_z = -1e30, min_z = 1e30;
for (size_t i = 0; i < verts.size(); ++i) {
if (verts[i][2] > max_z) { max_z = verts[i][2]; north_pole = i; }
if (verts[i][2] < min_z) { min_z = verts[i][2]; south_pole = i; }
}
// Constrain poles
solver.addConstraint(north_pole, 1.0);
solver.addConstraint(south_pole, 0.0);
// Solve for a smooth scalar field
auto field = solver.solve();
sphere.addVertexAttribute("latitude_param", field);
std::cout << "Solved harmonic diffusion on sphere with "
<< sphere.vertexCount() << " vertices\n";
std::cout << "North pole value: " << field[north_pole] << "\n";
std::cout << "South pole value: " << field[south_pole] << "\n";
return 0;
}
Implementation Notes
- The solver uses Jacobi iteration on the graph Laplacian of the mesh.
- Convergence speed depends on mesh connectivity and the distribution of constraints.
- For large meshes, consider increasing
maxIterand monitoring convergence. - Constrained vertices are never modified during iteration.
- Works with both 2D and 3D meshes (
Mesh<2>andMesh<3>).