I think it is very easy for the developers to implement a proper orthogonal decomposition for unsteady flow with equal spaced timesteps using Snapshot POD algorithm described in chapter 3.2 of http://web.mit.edu/kwillcox/Public/Web/BTTanMS.pdf
The algorithm is:
0. get timestepvalues of interest as ti, i=1…N
load field P of two timesteps such as as Pi=P(ti),Pj=P(tj)
calculate the correlation Rij = innerproduct(Pi,Pj)/N, the definition of inner product could be integration of Pi*Pj over the volume.
get the eigen value lambdai and corresponding vector eVii of matrix {Rij}
construct the i-th POD basis psii = sum(dot(eVij,Pj),j=1…N), usually, only the first bases are used.
reconstruct Prm field using first m POD bases:
Prm = sum(lambdai * psi_i, i = 1… m)
output the psii and Prm
I just tried to implement this algorithm using python, but the problem is I need to open the same case file two times, and using a pipeline to integrate over the volume. And I do not know how to sum over all N timesteps weighted with the eigen vector eV_i. It is very complex in python on client side. I think it is better to implement it in C++ as a filter.
I’ve implemented a snapshot method in VTK and used in some internal projects involving unstructured code, but it would be nice to have it directly in ParaView and generalise a few things.
One major benefit of having a vtkSnapshotPODFilter would be that you can feed into it from any pipeline. For instance if you have a velocity field but you want to do a POD of vorticity, you should just pass it via Gradient and Calculator and then POD that.
Also, it would be nice to be able to generalise the dot product. If you are doing POD of a vector valued function the dot product needs to take that into account somehow.
I think it’s a good case for a PV plugin.
I just came across this topic and I am assuming that no one has build such a plugin yet? I am happy to give it a go and I’ve got some projects in our programme that could use it, so could spend some time this Autumn on it.
Another quick idea here for some functionality of a plugin.
If combined with Catalyst, it could also do computation of POD mode temporal coefficients i.e. projections of current solution onto a POD mode. Typically, you are not interested in POD model, but rather how the temporal coefficients of each mode change over time. This is also something you want at high-temporal resolution. So after computing POD, another filter could use the output to get these coefficients on the fly.
Having this in ParaView may save a lot of repetitive developments. At the moment to do POD for your favourite code you need to implement it internally. But if you have a PV reader and a Catalyst adapter you could do it for free, although I concede that this is two ifs, which may be two too many.
I’ve finally manage to implement a classic snapshot method as a filter. I based it heavily off the average filter and made three passes: one to compute the average, second to compute the projection matrix and third to compute the modes. I did eigenvalue decomposition with Eigen.
I am not too happy with my implementation yet, because:
I only process cell data.
There’s redundant data load which may be unavoidable in the general case. Every time I load a time step, I subtract the mean and perform a computation. For the double loop I make a temporary copy of time step in the outer index.
The inner product is computed naively with std::inner_product. Cell volume or other discretisation is not incorporated. If anyone runs it with high-order mesh they may want to use quadratures to compute the inner product, but I don’t know how to build this machinery.
Also, if you read about it, then you probably know that under some circumstances eigenvalue problem of the matrix projection matrix is equivalent with an SVD on the data matrix. It may be a good idea to implement this as “Fast method” at least for point data but I am not sure how to implement it without loading all the data - probably not doable in a general HPC context?