sandbox/jmf/Hodge/hodge.h
Hodge Decomposition
Let \Omega^k the space of the k-forms on a closed compact n-dimensional manifold, any k-form \omega can be expressed as \displaystyle \omega = d \alpha + \delta \beta + \gamma for some k-1 form \alpha, a k+1 form \beta and \gamma \in \Omega^k. Where in the exterior calculus (see Exterior Algebra)
- d is the differential exterior derivative
- \delta is the codifferential defined by \star d \star
and \star is the Hodge operator.
Given a k-form \omega there are unique \alpha, \beta,\gamma (Hodge theorem, see H. Flanders, Differential Forms with Applications to the Physical Sciences (Dover Books on Mathematics)) which can be found by solving
- \delta \omega = \delta d \alpha
- d \omega = d \delta \beta
- \gamma = \omega - d \alpha - \delta \beta
In R^2 a vector X = (u,v) is associated to a 1-form \omega = u dx + v dy
we solve \delta \omega = \delta d \alpha
- \delta \omega = \star d \star \omega \rightarrow \delta \omega_X = \star d ( -v dx + u dy)
- \delta \omega = \star (-v_y dy \wedge dx + u_x dx \wedge dy)
- \delta \omega = u_x + v_y
As \omega_X is a 1-form that implies \alpha \in \Omega^0 a function of real values, we found then
- d \alpha = \alpha_x dx + \alpha_y \ dy
- \delta d \alpha = \star d \star d \alpha = \alpha_{xx} + \alpha_{yy}
The first equation is then \displaystyle \alpha_{xx} + \alpha_{yy} = u_x + v_y a Poisson equation for \alpha.
Structure for the solver :
- omega,
- gradb,
- rotc,
- h
are mandatory vectors giving the Hodge decomposition. If the scalar alpha and beta exist they will return the scalar fields.
#include "poisson.h"
struct Hodge {
// mandatory
vector omega;
vector gradb;
vector rotc;
vector h;
// optional
scalar alpha;
scalar beta;
};
Call the Hodge decomposition
trace
mgstats hodge (struct Hodge p)
{
vector omega = p.omega;
vector gradb = p.gradb;
vector rotc = p.rotc;
vector h = p.h;
// Local
scalar b[];
scalar alpha[];
scalar beta[];
Check the existence of alpha et beta
if (p.alpha.i) {
alpha = p.alpha;
}
if (p.beta.i) {
beta = p.beta;
}
paranoia
boundary ((scalar *){omega});
Filling the rhs of the Poisson equation
foreach()
{
#if order == 2
b[] = (omega.x[1,0] - omega.x[-1,0])/2./Delta + (omega.y[0,1] - omega.y[0,-1])/2./Delta;
#else
b[] = (omega.x[-2,0] - 8.*omega.x[-1,0] + 8.*omega.x[1,0] -omega.x[2,0])/12./Delta;
b[] += (omega.y[0,-2] - 8.*omega.y[0,-1] + 8.*omega.y[0,1] -omega.y[0,2])/12./Delta;
}
#endif
Solve \nabla^2 \alpha = b using the Poisson solver
Now we apply the same procedure to d \omega = d \delta \beta
d\omega = \left( -\frac{\partial\,u}{\partial y} + \frac{\partial\,v}{\partial x} \right) \mathrm{d} x\wedge \mathrm{d} y
and
d \star d \star \beta = \left( \frac{\partial^2\,\beta}{\partial x ^ 2} + \frac{\partial^2\,\beta}{\partial y ^ 2} \right)d x\wedge d y
we have still a Poisson equation
\displaystyle \nabla^2 \beta = b = \left( -\frac{\partial\,u}{\partial y} + \frac{\partial\,v}{\partial x} \right)
foreach()
{
#if order == 2
b[] = (omega.y[1,0] - omega.y[-1,0])/2./Delta - (omega.x[0,1] - omega.x[0,-1])/2./Delta;
#else
b[] = (omega.y[-2,0] - 8.*omega.y[-1,0] + 8.*omega.y[1,0] -omega.y[2,0])/12./Delta;
b[] -= (omega.x[0,-2] - 8.*omega.x[0,-1] + 8.*omega.x[0,1] -omega.x[0,2])/12./Delta;
}
#endif
boundary ({beta,b});
Solve Poisson problem
s = poisson (beta, b,tolerance = 1e-6);
Finally from the scalar fields \alpha and \beta$ we compute the vectors \displaystyle gradb = d \alpha \displaystyle rotc = \delta \beta and \gamma by subtraction.
Compute vectors
foreach()
foreach_dimension()
#if order == 2
gradb.x[] = (alpha[1,0] - alpha[-1,0]) / 2./Delta ;
#else
gradb.x[] = (alpha[-2,0] - 8*alpha[-1,0]+ 8.* alpha[1,0] - alpha[2,0]) / 12./Delta ;
#endif
struct { double x, y; } a = {-1., 1.};
foreach()
foreach_dimension()
#if order == 2
rotc.x[] = a.x * (beta[0,1] - beta[0,-1]) / 2./Delta ;
#else
rotc.x[] = a.x * (beta[0,-2] - 8*beta[0,-1]+ 8.* beta[0,1] - beta[0,2]) / 12./Delta ;
#endif
boundary ( (scalar *){gradb,rotc});
Compute h
foreach()
foreach_dimension()
h.x[] = omega.x[] - gradb.x[] - rotc.x[];
boundary ((scalar *){h});
return s; // Fix : better return
}