Piecewise Constant Velocity Advection
I feel it’s more natural to express position of vortices in barycentric coordinates along with face-id. Then the advection is to be carried on barycentric coordinates rather that the world coordinate of the vortex. Let where each and is a face-id.
Then from stream function formulation we know that
If we want to perform the advection using barycentric coordinates, we need . Further, using multivariate chain-rule we can write (we assume that , the face-id is constant for a time-step)
Now from and
where is a unit face normal for the incident face. We can rearrange using vector triple product identity as:
Further, the stream function can be written down in terms of barycentric coordinates , where is value of the stream function at in face-id . Then,
using this in we get
Also, is face-wise constant which is given as:
where is area of triangle with face-id , and is edge opposite to the vertex . Using this in Eq. results in lot of cancellation and simplification and finally we get:
Note that , i.e., , and we can verify that Eq. satisfy this constraint.
Edge Crossing
In the reformulation above, we assumed that the face ID is constant. So what happens when a point vortex crosses an edge? This can be handled by checking for a negative barycentric weight. In that case, we can use a discrete Levi–Civita connection, unfold-translate-rotate-fold adjacent triangles to move the point from one face to another.

Removing Influence of Singular Self Term
After implementing above, the point vortex’s motion was different that expected. After further analysis it turned out to be cause of the self induced velocity due to singular part of a vortex on itself. Looking back a the analytical Green’s Function formulation, this is obvious as well.
Where, is velocity at the point vortex and is Green’s kernel, solution to Poisson equation for delta functions on RHS. Notice the part of the sum, this implies that we should exclude a vortex’s influence on itself.
This exclusion seems to be motivated from the fact that evaluation of the Green’s function at the core results in a singular term with infinite velocity. We get rid if this singularity by a barycentric splat of the point vortex to its incident triangle vertices. But after implementing this, it was evident in the simulation that the split of singular part is influencing motion of a point vortex inside triangle. By observation it looked like, after splitting, each triangle vertex acted as a point vortex. This induced a finite, nonzero velocity at the original location of the point vortex. This affected the time evolution and resulted in wrong vortex trajectories.
First fix, I treated each triangle vertex a point vortex with strength . As triangle is a planer domain, I used 2D planer Biot-Sawart Law to calculate the velocity at the original vortex position . Then the final velocity at the point vortex location is .
But our mesh domain is a linear approximation and by above approach, we were using wrong model to calculate the . We need to use the same DEC machinery to calculate the self velocity term. One thing to notice is that point vortex’s self velocity (due to the singular part) is a local effect, so we can take a local patch of mesh around the vortex triangle, formulate a Poisson problem with Dirichlet boundary condition. Then the velocity inside the source face would be a true representation for .
But as you could see this is numerically very expensive as we need to setup and solve a mini Poisson problem for each face for every vortex position! But after a lot of pondering I realized, we can actually precompute velocity basis for self velocity per face. Then when needed, just take weighted average of these basis using barycentric weights and vortex strength to get the . This cuts down computation from multiple time per face to once per face. Further, we can do lazy computation to avoid calculating all basis at once.
Below is a detailed sketch of how to get these self velocity basis

Then, given we get self velocity as:
Using this singular term removal I was able to get at least a sane behavior, but the path taken by point vortex still doesn’t look natural. This seems be advection artifacts, due to discontinuous velocity field, as each Poisson solve just assumes that the current state is an accurate evolution of previous. But due to artifacts in the mesh, around corners and all the vortice’s relative motion is not accurate enough which is corrupting the next step.
Hamiltonian of the system is fluctuating in range of 0.1 but then starts to grow (mostly due to numerical error) after ~5000 steps.
